Compare commits

...
617 Commits
Author SHA1 Message Date
roberto@natty32 6eed48b28d updated Changelog and copyright year 2011-04-06 09:29:46 +02:00
roberto@netbsd64 9c5d289098 better locking for NetBSD and OpenBSD 2011-04-06 08:16:03 +02:00
roberto@solarisexpress 42ab7f23d8 added timegm to solaris 2011-04-06 06:03:17 +00:00
roberto@natty32 c9c2f4232e preparing for 0.9.7.2 release 2011-04-06 05:06:38 +02:00
roberto@longshot d4f23cc6bd use realpath() for document_root 2011-04-05 20:55:48 +02:00
roberto@natty32 b0db67d4d4 refactored post limit management 2011-04-05 16:51:40 +02:00
roberto@natty32 703cad6715 disallow empty socket names 2011-04-05 11:32:15 +02:00
roberto@natty32 667d67460f do not build netlink support (still useless for non-third-party plugins) 2011-04-05 09:00:58 +02:00
roberto@natty32 35cf9ae328 implemented exc_info in WSGI start_response and added --reload-on-as and --reload-on-rss 2011-04-05 08:58:22 +02:00
roberto@natty32 c04131af4b fixed syslog support 2011-04-04 17:17:47 +02:00
roberto@natty32 9cc4db1a12 various fixes 2011-04-04 09:46:17 +02:00
roberto@natty32 b326500913 --static-map mountpoint=documentroot option 2011-04-04 08:31:17 +02:00
roberto@natty32 a26579fcf5 better plugin loading 2011-04-03 08:18:51 +02:00
roberto@natty32 a2b9c44433 -ldl should be used only for Linux 2011-04-02 15:57:57 +02:00
roberto@natty32 c3b97da1d4 various Riccardo Magliocchetti build fixes 2011-04-02 15:26:00 +02:00
roberto@natty32 048cf0232a nailed connection between emperor and rabbitmq 2011-04-01 16:11:18 +02:00
roberto@natty32 89c113bee6 added EXILE mode for vassals 2011-04-01 08:35:20 +02:00
roberto@natty32 6b9969a302 allow emperor config files to be taken via http 2011-04-01 08:09:34 +02:00
roberto@natty32 a6e7513d2a declare exchange automatically 2011-04-01 07:13:09 +02:00
roberto@natty32 8a04f4810f allow vassals configuration to be stored on amqp/rabbitmq servers 2011-04-01 06:31:54 +02:00
roberto@natty32 1d9d443de0 amqp/rabbitmq emperor fixes 2011-04-01 05:17:50 +02:00
roberto@natty32 00e5809a71 preliminary amqp/rabbitmq support for emperor 2011-04-01 03:14:51 +02:00
roberto@freebsd64 07ba4a040b fixed freebsd kvm_open 2011-03-30 20:48:01 +02:00
roberto@mrspurr 7b319d230a allow building of psgi plugin without ithreads 2011-03-30 08:03:48 +02:00
roberto@natty32 641bc2daec fixed unbitstaff build profile 2011-03-29 12:06:13 +02:00
roberto@dj2 fbaa30cc08 various fixes 2011-03-28 11:31:40 -05:00
roberto@dj2 a0c2c9056b fixed a couple fo emperor race conditions 2011-03-28 09:37:17 -05:00
roberto@dj2 30ab5fd76b added --exit-on-reload 2011-03-28 07:31:51 -05:00
roberto@dj2 30beab4017 fixed a regression in setgroups() 2011-03-28 05:38:29 -05:00
roberto@dj2 4ec1493b09 fixed subscription system 2011-03-28 04:29:04 -05:00
roberto@dj2 e7cbe9709e build netlink support in Linux 2011-03-28 04:17:07 -05:00
roberto@dj2 aacaeba525 shared sockets support 2011-03-28 04:15:31 -05:00
roberto@dj2 6e4da5efb7 add netlink library 2011-03-28 04:11:31 -05:00
roberto@natty32 87443a4ff2 Added tag 0.9.7.1 for changeset 486e7760bcbc 2011-03-26 09:39:57 +01:00
roberto@natty32 9746759c68 fixed changelog before official release 2011-03-26 09:39:53 +01:00
roberto@natty32 170ee2b98a date was wrong in 0.9.7.1 2011-03-26 09:38:21 +01:00
roberto@natty32 938fb777dd uWSGI 0.9.7.1 2011-03-26 09:36:11 +01:00
roberto@natty32 33e1aafcd1 Added tag 0.9.7.1 for changeset d9b9b540f7dc 2011-03-26 09:35:31 +01:00
roberto@natty32 597ee90041 add sys.abiflags if necessary 2011-03-26 09:27:30 +01:00
roberto@natty32 e87e54ea28 allow --namespace-net and fix python library name 2011-03-26 09:18:52 +01:00
roberto@natty32 5c64c1ac3f fixed post-buffering without pep3333-input 2011-03-25 19:11:53 +01:00
roberto@natty32 c611cbc2ca fixed current_wsgi_req in multithreading without cores 2011-03-23 11:59:05 +01:00
roberto@sirius 9d051f4171 fixed a buf on older OSX versions (i hope) 2011-03-22 19:34:12 +01:00
roberto@sirius 6aee788678 fixed cmsg parsing 2011-03-22 17:21:19 +01:00
roberto@natty32 425a45caa7 updated banner message in debug mode 2011-03-22 17:02:20 +01:00
roberto@natty32 0571601e02 added --map-socket 2011-03-22 14:55:54 +01:00
roberto@natty32 c1992c8c7a added --check-cache 2011-03-22 12:12:03 +01:00
roberto@natty32 bd913870c7 fixed setup.py 2011-03-21 10:36:52 +01:00
roberto@natty32 7a479dd47f add 304/If-Modified-Since support for --check-static <dir> 2011-03-21 10:31:50 +01:00
roberto@natty32 7ae77aa58d added UWSGI_CACHE_GET dynamic variable 2011-03-20 21:24:32 +01:00
roberto@natty32 97a4260d44 added --pidfile2 and --logfile-chown 2011-03-20 08:05:27 +01:00
roberto@mrspurr b90d711764 allow python modules to be on http server 2011-03-20 07:51:56 +01:00
roberto@mrspurr 22de5b523e reintroduce modifier1 30 2011-03-19 17:03:00 +01:00
roberto@mrspurr 5798b824c0 forbid daemonizing in vassal mode 2011-03-19 11:03:16 +01:00
roberto@goyle 4cbf6cfc33 various fixes in touch_reload 2011-03-19 09:33:28 +01:00
roberto@mrspurr 8b55460156 added persistence for queue 2011-03-18 20:20:36 +01:00
roberto@mrspurr a61d48a451 fixed stackless support 2011-03-18 08:14:12 +01:00
roberto@mrspurr b9f4d57d67 applied activestate fix for --root support in setup.py 2011-03-18 07:15:10 +01:00
roberto@natty32 92cd36d14d ready for first stable release 2011-03-17 09:15:52 +01:00
roberto@natty32 f74e61b126 fixed psgi compilation 2011-03-16 21:29:52 +01:00
roberto@natty32 c8b4ba2b5b updated iobound_async example and improved pep3333-input 2011-03-16 20:54:54 +01:00
roberto@natty32 0a15ba1c5b remove stackless support, move it to async plugin 2011-03-16 13:12:50 +01:00
roberto@natty32 7ee5948233 better error reporting on failed open/fopen 2011-03-16 12:14:41 +01:00
roberto@natty32 85c8bcf9d2 removed memory leak in greenlet plugin 2011-03-16 11:12:55 +01:00
roberto@natty32 67394c6664 added greenlet plugin 2011-03-16 11:02:05 +01:00
roberto@silente 66ef7d8229 remove uGreen compilation on unsupported platforms 2010-12-29 23:06:47 +01:00
roberto@solarisexpress 3773bc69f2 fixed ldap solaris support 2011-03-16 09:48:52 +00:00
roberto@natty32 912416b119 fixed openldap support 2011-03-16 09:45:15 +01:00
roberto@solarisexpress 7dfe125013 solaris fixes 2011-03-16 09:39:02 +00:00
roberto@mrspurr 87db34ef0b removed setjmp code 2011-03-16 07:46:11 +01:00
roberto@natty32 d4f75ab53c re-added ugreen support (better and faster) 2011-03-16 07:28:23 +01:00
roberto@natty32 dc97e8fce5 new help system 2011-03-15 12:14:22 +01:00
roberto@natty32 b3965d9d67 updated async support 2011-03-15 10:45:23 +01:00
roberto@natty32 7ee90d1e12 fixed python uwsgi.cache_get 2011-03-12 14:52:11 +01:00
roberto@sirius 9d8b373e4f uWSGI 0.9.7-rc3 2011-03-12 14:21:16 +01:00
roberto@natty32 a068a7eb5b added support for cache backing store 2011-03-12 14:14:43 +01:00
roberto@natty32 aa004c1893 less verbose file monitoring 2011-03-12 09:31:14 +01:00
roberto@natty32 9a9c149370 fixed emperor waitpid and erlang list encoding 2011-03-12 07:35:41 +01:00
roberto@natty32 9e6e226e4b improved snmp agent and fixed cache modifier 4 2011-03-11 11:55:44 +01:00
roberto@mrspurr 06c2aed0e0 add modifier 3 in cache plugin 2011-03-11 10:57:39 +01:00
roberto@natty32 df4f610cfc preliminary cpu-affinity support 2011-03-11 07:37:43 +01:00
roberto@natty32 64249abae1 improved ldap support 2011-03-10 19:14:13 +01:00
roberto@sirius 94f4be58bd auto configure ldap support 2011-03-10 10:40:56 +01:00
roberto@sirius 35987d3741 added --allowed-modifiers 2011-03-10 10:21:08 +01:00
roberto@natty32 be73e00dde merge 2011-03-10 09:56:33 +01:00
roberto@natty32 a5f272f337 fixed a bug in getopt_long 2011-03-10 09:56:04 +01:00
roberto@sirius 406691aa69 uWSGI 0.9.7-rc2 2011-03-09 11:26:27 +01:00
roberto@natty32 6827b3bf15 cron-like interface added to signal framework 2011-03-09 10:33:44 +01:00
roberto@natty32 2055a1472f great fix suggested by Damjan Georgievski for linux namespaces 2011-03-08 14:17:30 +01:00
roberto@natty32 f4f9018068 fixed multithreading + max-requests 2011-03-08 11:45:37 +01:00
roberto@sirius 3e82b5cd33 improved configuration system 2011-03-07 16:06:59 +01:00
roberto@sirius 07036bce20 fix %v usage in emperor 2011-03-07 11:52:44 +01:00
roberto@sirius a4a7a75f29 uWSGI 0.9.7-rc1 2011-03-07 09:42:53 +01:00
roberto@natty32 02d6006b2f added %v in emperor 2011-03-06 19:21:09 +01:00
roberto@natty32 e8e5f11c66 use sigaction() instead of signal() 2011-03-05 17:20:10 +01:00
roberto@natty32 e53a6fa4c0 fixed http fd passing on POST 2011-03-04 14:23:36 +01:00
roberto@natty32 c478b0a0c8 added uwsgi.erlang_register_process 2011-03-04 12:07:07 +01:00
roberto@natty32 5f207e6978 fix getsockname on unbound sockets 2011-03-04 09:01:14 +01:00
roberto@natty32 a2b74d0afd fixed linux namespace on recent kernel 2011-03-04 08:20:20 +01:00
roberto@maverick64 b867b11de3 fixed python2.x threads 2011-03-03 17:17:27 +01:00
roberto@maverick64 806765d1d3 fixed python3.2 threads 2011-03-03 17:15:01 +01:00
roberto@sirius 62d2b97e17 export build date 2011-03-03 14:06:29 +01:00
roberto@sirius c04e339034 report clustering without a socket 2011-03-03 11:07:58 +01:00
roberto@sirius 927b495646 nuclear blast all the processes on initialization error 2011-03-03 10:38:19 +01:00
roberto@mrspurr 57b5392590 fixed gateways reloading 2011-03-03 09:52:57 +01:00
roberto@mrspurr 463030108f fixed vacuum 2011-03-03 09:17:03 +01:00
roberto@netbsd64 46dd754264 NetBSD fixes 2011-03-02 19:54:13 +01:00
roberto@silente 12d9641b66 OpenBSD, endianess and clustering fixes 2010-12-16 07:21:51 +01:00
roberto@maverick64 6cb1203d26 fixed post buffering in python 2011-03-02 17:22:12 +01:00
roberto@maverick64 23d0ec333e encode python string/binary to erlang binary 2011-03-02 11:17:12 +01:00
roberto@maverick64 da579fd308 fix refcnt in erlang->python translation 2011-03-02 08:54:01 +01:00
roberto@longshot 14152bc999 removed broken log rotation 2011-03-01 20:55:04 +01:00
roberto@sirius 6c32e5f2e2 fixed no_argument options in ini and yaml parsing 2011-03-01 16:38:45 +01:00
roberto@freebsd64 62f74f2b60 uWSGI 0.9.7-beta1 2011-03-01 10:47:32 +01:00
roberto@maverick64 6ac7f6db7f python 3.2 fixes 2011-03-01 10:43:43 +01:00
roberto@mrspurr 388a836bbc added Changelog for beta1 2011-03-01 10:20:37 +01:00
roberto@mrspurr f0187e8b0f added --reload-mercy 2011-03-01 10:04:36 +01:00
roberto@sirius c698b82c30 do not rely on exit code for server reloads 2011-02-28 17:39:09 +01:00
roberto@fiorenzo afb3e3636e fixed lua and psgi plugins 2011-02-28 15:26:05 +01:00
roberto@cable 774548f268 --attach-daemon fixes 2011-02-28 08:47:04 +01:00
roberto@longshot ee38901855 various rack/rails fixes 2011-02-27 09:29:01 +01:00
roberto@longshot a07ecdb3e3 multiline headers in Rack plugin 2011-02-27 07:10:29 +01:00
roberto@longshot 143c286f3b fixed --eval 2011-02-27 05:54:20 +01:00
roberto@longshot 5f2f13c49e another --processes auto fix 2011-02-27 05:15:15 +01:00
roberto@longshot 2c19a031c7 added --processes auto 2011-02-26 20:28:26 +01:00
roberto@mrspurr a10e67538a passive clustering support 2011-02-26 15:42:56 +01:00
roberto@fiorenzo 4387075930 multicast clustering in http router 2011-02-26 15:25:46 +01:00
roberto@fiorenzo 6ec1eb5c90 added --harakiri-verbose 2011-02-26 11:21:46 +01:00
roberto@fiorenzo 6ac1cbe913 fixed python2.5-erlang bridge 2011-02-25 18:40:32 +01:00
roberto@fiorenzo 4923326bdd another fix for pyerl 2011-02-25 17:53:09 +01:00
roberto@sirius 0f8ca18e0d erlang build fix 2011-02-25 17:35:57 +01:00
roberto@mrspurr 7666e16072 fixed urack.rb 2011-02-24 19:22:22 +01:00
roberto@mrspurr a42f6e5d18 fixed a stupid bug in fd passing 2011-02-24 19:13:34 +01:00
roberto@sirius 67b22ff796 added iterations to uwsgi.add_rb_timer() 2011-02-24 10:50:52 +01:00
roberto@sirius 28c14f4d8c added uwsgi.add_rb_timer() 2011-02-24 10:29:06 +01:00
roberto@sirius 7133069ee9 updated signal framework to the new api 2011-02-24 09:48:28 +01:00
roberto@lupo b752425223 fixed REMOTE_ADDR in http router 2011-02-23 21:18:33 +01:00
roberto@lupo c5367bb338 http timeout fixes 2011-02-23 21:10:23 +01:00
roberto@sirius d1342241bd rbtree timers 2011-02-23 20:54:52 +01:00
roberto@cable 05be07aab4 removed debug from real gil 2011-02-23 10:29:01 +01:00
roberto@mrspurr 7f4f16e96a fixed ini/yaml parsing with optional values, added UWSGI_SETENV var 2011-02-23 09:35:38 +01:00
roberto@lupo f11664642f add REMOTE_ADDR in http router 2011-02-23 05:50:35 +01:00
roberto@lupo 28b074b6ea always export QUERY_STRING in http router 2011-02-22 15:18:49 +01:00
roberto@lupo f43161c939 subscription system fix 2011-02-22 14:10:54 +01:00
roberto@sirius d52b7111ea fixed reloading 2011-02-22 13:47:29 +01:00
roberto@sirius 9331d1154e damn, another fix for spooler leak 2011-02-21 11:03:46 +01:00
roberto@sirius 364a580090 fixed a leak in the spooler 2011-02-21 10:17:28 +01:00
roberto@lupo f33fa5005a better subscription system 2011-02-21 09:28:38 +01:00
roberto@lupo 8029d01b8b report client REMOTE_ADDR in SIGPIPE 2011-02-21 07:46:37 +01:00
roberto@lupo 69586a6134 fixed a couple of leaks spotted by Riccardo and added uwsgi.listen_queue() 2011-02-21 07:44:37 +01:00
roberto@lupo 7c9c50c6a9 --master-as-root can be used with gateways 2011-02-21 06:47:23 +01:00
roberto@lupo 97139a27d7 SERVER_PORT support in http server 2011-02-21 05:49:52 +01:00
roberto@mrspurr 3b67033d65 http fixes and new subscriber infrastructure 2011-02-20 20:06:26 +01:00
roberto@mrspurr ec08632a29 fixed python <= 2.5 support 2011-02-19 08:55:41 +01:00
roberto@mrspurr eea64e0178 new caching modifier2 2011-02-19 08:39:28 +01:00
roberto@goyle 78096fab30 cache items can have a 16bit flags 2011-02-18 19:34:02 +01:00
roberto@goyle 86fcd13dd9 structure for future response caching 2011-02-18 19:31:58 +01:00
roberto@goyle 4badecdbbc --attach-daemon option 2011-02-18 16:11:24 +01:00
roberto@fedora32 8d1a0d6a13 better check for linux namespace support 2011-02-17 15:24:24 +01:00
roberto@goyle b102b2979b allow uwsgi queue to be used as a stack 2011-02-17 08:04:17 +01:00
roberto@arch32 393235fbfe python3 fixes 2011-02-16 16:56:51 +01:00
roberto@goyle 183a109119 another bunch of async optimizations 2011-02-16 16:42:33 +01:00
roberto@goyle bcff6e0173 various fixes 2011-02-16 15:44:53 +01:00
roberto@goyle 3bd2c3a573 merge 2011-02-16 08:12:53 +01:00
roberto@goyle afba91ad61 added uwsgi queue subsystem 2011-02-16 08:12:21 +01:00
roberto@goyle a34c0f5556 http event optimization 2011-02-15 14:24:53 +01:00
roberto@openbsd32 3fd41a3d2e OpenBSD fixes 2011-02-15 11:53:56 +01:00
roberto@openbsd32 1c5ba25437 use gcc -dumpversion 2011-02-15 10:34:58 +01:00
roberto@arch32 f7ff6b5488 fix gcc version detect 2011-02-15 09:54:22 +01:00
roberto@goyle 53ac53167b osx rwlock fix 2011-02-15 08:39:42 +01:00
roberto@maverick64 c4eccd0d93 first attempt of a better wsgi.input 2011-02-14 20:48:01 +01:00
roberto@maverick64 7744285dc3 move caching locking to rwlock 2011-02-13 18:58:51 +01:00
roberto@maverick64 238c98c0bd a bunch of caching fixes 2011-02-12 10:59:20 +01:00
roberto@maverick64 f9a9ef5752 new cache subsystem 2011-02-12 10:33:12 +01:00
roberto@maverick64 6e5e357a36 suppress epoll_wait warning on reload 2011-02-11 05:36:37 +01:00
roberto@maverick64 0c4004ed14 fixed cache expire (again) 2011-02-11 05:10:42 +01:00
roberto@maverick64 008cd13c4f fixed cache expire 2011-02-10 18:39:29 +01:00
roberto@maverick64 7f3ba8324a fixed uwsgi.cache_exists 2011-02-10 18:37:09 +01:00
roberto@mmaverick64 e9002f2111 allow empty string in cache python api 2011-02-10 15:07:46 +01:00
roberto@maverick64 8f161909bb erlang_recv re-added 2011-02-10 09:48:08 +01:00
roberto@maverick64 1eea49a010 another bunch of erlang new features 2011-02-09 20:28:16 +01:00
roberto@maverick64 e62679cc26 another bunch of erlang features: atoms are mapped to unicode 2011-02-09 12:32:26 +01:00
roberto@sirius f8f9325cbc osx fixes 2011-02-08 16:10:51 +01:00
roberto@maverick64 fa1dd3fbfd the new (production-friendly) HTTP server 2011-02-08 16:04:41 +01:00
roberto@maverick64 0288313524 updated async stack 2011-02-07 10:28:11 +01:00
roberto@solarisexpress df18d66319 various solaris fixes 2011-02-05 22:29:54 +00:00
roberto@maverick64 e8eb86f998 merge 2011-02-05 15:17:13 +01:00
roberto@maverick64 534ff245f2 new Erlang subsystem 2011-02-05 15:16:22 +01:00
roberto@sirius 172654d409 fixed kqueue support 2011-02-04 09:48:38 +01:00
roberto@maverick64 4dea7cfb4b --fastrouter-use-base --fastrouter-use-pattern, multi fd wait in async stack 2011-02-04 09:09:58 +01:00
roberto@maverick64 f7955858bf better processes intercommunication 2011-02-03 21:02:26 +01:00
roberto@maverick64 fb5a5ddadd added uwsgi.erl in contrib 2011-02-03 16:25:56 +01:00
roberto@freebsd64 2bacd79c43 fixed a couple of leaks 2011-02-03 11:10:16 +01:00
roberto@freebsd64 6ca539497d add %d to magic table 2011-02-03 07:56:40 +01:00
roberto@mrspurr 78f3524fcb fixed kqueue 2011-02-02 19:20:46 +01:00
roberto@maverick64 937b2de41b the uWSGI fastrouter 2011-02-02 16:38:51 +01:00
roberto@maverick64 a07c79f7be moved listen queue to 100 by default 2011-01-30 05:55:34 +01:00
roberto@maverick64 9562c81590 the new spooler is working 2011-01-29 11:48:46 +01:00
roberto@maverick64 0a37852c5f ready to port the spooler to the new api 2011-01-29 10:08:35 +01:00
roberto@maverick64 460b78857c 64K are greater than 10K.... 2011-01-28 14:32:03 +01:00
roberto@maverick64 ac0e0a9f9e patch by Damjan Georgievski to allow compilation without xml 2011-01-27 18:20:07 +01:00
roberto@maverick64 740f16fe62 added exception for python cache_set 2011-01-27 18:04:35 +01:00
roberto@maverick64 faa0995c9c fix fd 0 usage 2011-01-27 15:41:47 +01:00
roberto@maverick64 dfff71a525 fixed xml and yaml parsing 2011-01-27 14:43:31 +01:00
roberto@maverick64 380d8cb3ea fixed --pyargv 2011-01-27 13:20:25 +01:00
roberto@maverick64 3f5aab2083 UWSGI_VASSAL_ support for Emperor, magic vars for configuration files 2011-01-27 09:27:55 +01:00
roberto@maverick64 2af5ef9016 added the uWSGI emperor 2011-01-26 16:29:49 +01:00
roberto@maverick64 f82dbfd300 support BROADCAST for clustering 2011-01-25 16:20:11 +01:00
roberto@maverick64 9cbf1c545d added uwsgi.fcgi() api function to allows uWSGI being a fastcgi proxy/router 2011-01-23 14:35:42 +01:00
roberto@maverick64 9ac598b9c3 better harakiri on threaded modes 2011-01-21 18:08:04 +01:00
roberto@maverick64 07dd0c2c0b Python3 support back to the future 2011-01-21 10:17:52 +01:00
roberto@maverick64 66b1cdd63c fixed threads startup 2011-01-19 07:59:59 +01:00
roberto@sirius 78980aab9e re-export uwsgi.env in non-threaded modes 2011-01-18 06:11:09 +01:00
roberto@sirius 0ac813be79 fixed reloading/respawn 2011-01-18 06:02:45 +01:00
roberto@maverick64 b09513bb2e xml,ini and yaml file can taken via http automagically 2011-01-17 22:02:13 +01:00
roberto@maverick64 c3e906f1ff threaded example 2011-01-16 09:32:58 +01:00
roberto@maverick64 666c1fec75 added support for cache_get, cache_set and call to PSGI 2011-01-15 19:05:05 +01:00
roberto@sirius 5d86ed46a3 fix psgi compilation 2011-01-15 17:43:01 +01:00
roberto@maverick64 2ee1c3ac32 allow append in build profiles 2011-01-15 14:26:46 +01:00
roberto@maverick64 ef530650c4 --dump-options 2011-01-15 14:07:58 +01:00
roberto@maverick64 fd1c7773ee gateways implementation -> proxy plugin 2011-01-15 12:56:10 +01:00
roberto@sirius 520ff8465b added exceptions counter 2011-01-14 14:49:45 +01:00
roberto@maverick64 170c66b000 fixed paste support: Plone threaded works perfectly 2011-01-13 18:10:13 +01:00
roberto@sirius c94206f7ba a huge list of threading fixes, we are near to ROCK SOLID threading mode 2011-01-13 11:42:59 +01:00
roberto@sirius f9158b39d8 pg async example 2011-01-11 10:38:20 +01:00
roberto@maverick64 daba88f947 --check-static option 2011-01-09 11:19:12 +01:00
roberto@maverick64 a7e4852621 --log-syslog option 2011-01-09 09:31:26 +01:00
roberto@maverick64 8a8d029357 lua build fixes 2011-01-09 08:07:51 +01:00
roberto@maverick64 b9621b620a reindent uwsgiconfig.py 2011-01-08 12:12:08 +01:00
roberto@debian32 cc0d656b86 fixed python multiapp loading 2011-01-08 12:01:19 +01:00
roberto@debian32 18080df77a fix for debian + python2.5 2011-01-08 11:26:45 +01:00
roberto@maverick64 059314e8f3 fixed uwsgi_rawlog 2011-01-08 09:47:26 +01:00
roberto@mrspurr 500e4e41fe uwsgi_rawlog() 2011-01-07 23:17:34 +01:00
roberto@sirius 8b21fb72b2 --logdate=strftime 2011-01-07 23:07:43 +01:00
roberto@mrspurr f8464ac733 fix debug build and better error reporting 2011-01-07 22:38:51 +01:00
roberto@sirius ac05ad1ef5 more tolerant uwsgi array parser 2011-01-07 16:03:29 +01:00
roberto@maverick64 ed5f501a19 improvements in multiple interpreter management 2011-01-06 19:45:43 +01:00
roberto@maverick64 515b9f2838 completely remove leave_open support (sorry that was a bad choice) 2011-01-06 11:48:10 +01:00
roberto@maverick64 d57ddff924 support for --mount option 2011-01-06 11:38:07 +01:00
roberto@maverick64 0a2da2a2ce jail-friendly setuid()/setgid() 2011-01-05 18:48:50 +01:00
roberto@maverick64 72f677bb0d working linux namespace support 2011-01-05 15:42:30 +01:00
roberto@sirius e176af1702 you can do RPC from uwsgicc 2011-01-04 17:42:48 +01:00
roberto@fiorenzo 6e748eafb9 the rpc plugin 2011-01-04 17:43:57 +01:00
roberto@sirius e11f84193a more rpc fixes 2011-01-04 16:02:44 +01:00
roberto@sirius ec4fbdff32 added generic functions for rpc 2011-01-03 20:52:23 +01:00
roberto@sirius d3ced01b43 added struct for uwsgi rpc 2011-01-03 20:25:00 +01:00
Riccardo Magliocchetti 64468ae69e uwsgicc: fix typo in template 2011-01-03 16:28:33 +01:00
Riccardo Magliocchetti 79d75e832f uwsgicc: template beautyfication, thanks to Simone Marcarino 2011-01-03 16:25:28 +01:00
roberto@sirius ae41506764 send log mesages via uwsgicc 2011-01-03 12:31:12 +01:00
roberto@fedora64 f0bb80b9b8 timerfd fix 2011-01-02 21:48:14 +01:00
roberto@solarisexpress 1955d63cad added support for solaris port event subsystem 2011-01-02 21:40:21 +00:00
roberto@mrspurr 4b2fdb3d30 OSX fixes 2011-01-02 18:53:14 +01:00
roberto@fedora64 d586fe2fb3 another test for linux namespace. They works perfectly 2011-01-02 17:51:50 +00:00
roberto@fedora64 924074175e using fedora14 as base for linux namespace support 2011-01-02 18:20:20 +01:00
roberto@fedora64 a64cbea6e8 old glibc fixes 2011-01-02 18:19:11 +01:00
roberto@sirius 9ef571b4fa allow usage of Linux namespace feautures 2011-01-02 12:15:52 +01:00
roberto@sirius 67666a1788 test for logrotation based on size 2011-01-02 10:43:00 +01:00
roberto@sirius e1daf1d360 add skel version of the uWSGI Control Center (flask+jinja2 app) 2011-01-01 12:42:17 +01:00
roberto@sirius 94f3b715e5 fixed cluster node names 2011-01-01 12:03:12 +01:00
roberto@sirius 31892a69df better cluster node management 2011-01-01 11:53:06 +01:00
roberto@sirius a43bc93492 add cluster_fd to master queue 2011-01-01 10:38:09 +01:00
roberto@sirius 8dd9149624 OSX build fixes 2010-12-28 10:10:37 +01:00
roberto@fiorenzo e422f7311a added register_signal tu lua api 2010-12-26 20:07:41 +01:00
roberto@fiorenzo bb093c7614 various Linux fixes 2010-12-26 18:33:12 +01:00
roberto@mrspurr 5186936c3a refactored signal framework 2010-12-26 10:33:50 +01:00
roberto 4269f0483f Leonid Borisenko patch for use absolute path as build profile 2010-12-26 09:39:30 +01:00
roberto@sirius 09f49bb5d6 added the list of healtchecks that will be available by default 2010-12-21 21:18:25 +01:00
roberto@sirius a054f2b968 various fixes for sendfile() and rack plugin 2010-12-21 08:38:43 +01:00
riccardo@unbit 149cf74fe6 compile on git Linux kernel 2010-12-21 07:23:51 +01:00
Riccardo Magliocchetti 123b3fd4b1 buildconf: update unbitstaff profile config 2010-12-20 12:07:28 +01:00
roberto@storm 2e18db2352 added inherit option for buildconf 2010-12-20 10:09:01 +01:00
roberto@freebsd64 d7c2856041 fixed timers on FreeBSD 2010-12-19 15:04:30 +01:00
roberto@mrspurr 07a87bdff3 fixed file monitor and timers on OSX 2010-12-19 14:58:01 +01:00
roberto@centos64 fca3c51351 fixed old linux kernel support 2010-12-19 13:05:37 +01:00
roberto@fiorenzo 70db2befb5 fully working file monitor and timer support for Linux/epoll 2010-12-19 12:50:36 +01:00
roberto@centos64 057fcb0693 remove timerfd() support for Linux kernel < 2.6.25 2010-12-19 09:18:45 +01:00
roberto@fiorenzo 051dc77712 move from poll() to epoll() on linux master.c 2010-12-18 16:48:43 +01:00
roberto@mrspurr 784191f127 moved master from poll() to kqueue() on OSX and *BSD 2010-12-18 14:58:44 +01:00
roberto@mrspurr 3454279ac7 thundering herd is solved even on OSX 2010-12-17 21:07:17 +01:00
roberto@fiorenzo e335cf5e96 solve the thundering herd bug 2010-12-17 20:58:57 +01:00
roberto@fiorenzo 44277b38cd leave_open should not be available for WSGI requests. It overcomplicates things 2010-12-17 18:05:41 +01:00
roberto@sirius 31bd3fa6c4 use uwsgi_signal framework for better/portable --no-orphans 2010-12-17 17:13:45 +01:00
roberto@freebsd64 3104f915e5 use umtx_* locking functions on FreeBSD 2010-12-17 13:44:33 +01:00
roberto@mrspurr 860a017060 remove a bit of pollution in the logs 2010-12-17 08:47:01 +01:00
roberto@mrspurr 23f00ec864 fixed mod_uwsgi for deflate filter 2010-12-16 22:56:24 +01:00
Riccardo Magliocchetti 69fd8aaa36 python plugin: prefer LIBDIR for LDFLAGS
Try to use LIBDIR instead of PREFIX as directory where to look for
python libraries to link with.
2010-12-16 18:41:35 +01:00
roberto@sirius 7ea77afb38 added base for lb (load-balancer) framework 2010-12-16 18:27:07 +01:00
roberto@sirius da577ef923 fixed poll() usage 2010-12-16 18:25:33 +01:00
roberto@sirius 26cae83139 build fix without udp 2010-12-15 18:37:56 +01:00
roberto@sirium a8c4f6bffe the cache can now contains upto 0xFFFFFFFF items, added uwsgi.cache_exists to the api 2010-12-15 10:47:01 +01:00
roberto@sirius eff66ef08f added router.lua 2010-12-13 18:16:15 +01:00
roberto@sirius 381da45196 completed caching framework api 2010-12-13 18:15:11 +01:00
roberto@goyle 43c347d20e use luaL_newstate 2010-12-12 18:29:03 +01:00
roberto@goyle fadee3242f LuaJit works perfectly and FAAAAST 2010-12-12 18:22:30 +01:00
roberto@goyle 27fda41398 first implementation of multi-request per connection (need optimization) 2010-12-12 17:37:28 +01:00
roberto@sirius f6f8dbecc0 better uwsgi_waitfd for nailed connections 2010-12-12 11:26:14 +01:00
roberto@fiorenzo 902991daa4 OOB for nailed connections 2010-12-12 11:22:39 +01:00
roberto@sirius 245ab6d815 various test for trying to allow pre-connected requests 2010-12-11 20:08:23 +01:00
roberto 96700a49e3 ok, i am stupid, added cache.c 2010-12-10 21:51:25 +01:00
roberto@sirius b75ba73264 caching infrastructure (need optimizations) 2010-12-09 19:54:37 +01:00
roberto@sirius 7d6f93d1cb uwsgi.recv_block and uwsgi.recv_frame 2010-12-07 05:38:57 +01:00
roberto@mrspurr 9aaf36141e extended the uwsgi api to allow easy implementation of websockets servers 2010-12-06 13:48:23 +01:00
roberto@mrspurr 68c6dd13b8 fixed fd close on uwsgirouter.py 2010-12-05 18:37:25 +01:00
roberto@mrspurr 8ac5176c4c fixed async routing 2010-12-05 10:52:01 +01:00
roberto@mrspurr fd49ba36eb more custom routing example and optimizations 2010-12-05 10:45:13 +01:00
roberto@mrspurr 047aac8426 export uwsgi.is_connected 2010-12-05 08:17:29 +01:00
roberto@mrspurr 103e7415f3 various threading fixes 2010-12-04 18:30:22 +01:00
roberto@mrspurr b64911d20e fixed uwsgirouter.py 2010-12-04 17:32:31 +01:00
roberto@mrspurr 2f970ce585 various async optimizations and routing python examples 2010-12-04 13:43:12 +01:00
roberto@sirius 47801964c4 merge 2010-12-03 18:27:14 +01:00
roberto@sirius da8eb4ad1b add uwsgirouter.py test script for upcoming custom routing 2010-12-03 18:26:29 +01:00
roberto@fiorenzo 320a2b8a7f various fixes 2010-12-01 13:35:40 +01:00
roberto@fiorenzo eab271e1e1 fixed a stupid bug 2010-11-30 14:27:39 +01:00
roberto@mrspurr d161962db1 pass custom apache variables via SetEnv 2010-11-28 09:54:31 +01:00
roberto@fiorenzo 36a3b408cf --proxy-node @self 2010-11-27 06:58:46 +01:00
roberto@fiorenzo 10af04becc uWSGI proxy is now cluster-aware 2010-11-27 06:06:22 +01:00
roberto@fiorenzo 4db259900e better virtual ip automagic 2010-11-27 05:37:29 +01:00
roberto@mrspurr fe4ba8130d cluster membership improvements 2010-11-27 04:58:20 +01:00
roberto@silente 4c4f92bad2 big endian fixes 2010-09-10 06:58:12 +02:00
roberto@fiorenzo 6f726d6370 wait forever for cluster configuration 2010-11-25 16:26:13 +01:00
roberto@fiorenzo c4f50fccfb various fixes 2010-11-25 16:21:25 +01:00
roberto@sirius 7e2daed0e8 fixed cluster logging (again) 2010-11-25 11:26:39 +01:00
roberto@sirius e4d3f79492 fixed cluster reloading 2010-11-25 11:10:58 +01:00
roberto@sirius d128a958cf cluster realod and logging 2010-11-25 11:07:27 +01:00
roberto@fiorenzo 0024bf56be fixed python module split 2010-11-25 09:53:56 +01:00
roberto@sirius 1d03fdee64 use recvfrom() instead of read() 2010-11-25 09:44:07 +01:00
roberto@sirius 152fb9cde9 cluster announce 2010-11-25 08:51:54 +01:00
roberto@mrspurr e6c5710657 use getifaddrs() instead of ioctl() 2010-11-25 07:33:47 +01:00
roberto@fiorenzo df0b3f7eb5 configuration can now be taken from the cluster nodes automagically 2010-11-24 18:55:15 +01:00
roberto@sirius f420bf3266 save multicast addr structure for performance 2010-11-24 18:28:54 +01:00
roberto@sirius 7a262159dc cluster configuration 2010-11-24 13:25:30 +01:00
roberto@fiorenzo 3dec2821f4 various new clustering implementations 2010-11-24 11:42:15 +01:00
roberto@sirius 652a9c5825 various multiapp and virtualhosting fixes 2010-11-22 11:15:02 +01:00
roberto@debian32 79c30fed23 added --manage-script-name 2010-11-21 15:21:06 +01:00
roberto 5ab8d800d8 more powerful --pymodule-alias directive 2010-11-20 17:57:48 +01:00
roberto@sirius 0beb7108e4 added python module aliases 2010-11-20 12:47:52 +01:00
roberto@sirius 356d59a38d fixed setup.py 2010-11-18 10:06:51 +01:00
roberto@sirius 87853d0ca3 fixed fiber support for kqueue 2010-11-17 15:38:48 +01:00
roberto c9056630b7 Fiber support is now working (no fd monitoring and sleep yet) 2010-11-17 15:06:31 +01:00
roberto@sirius a4120efabe added experimental fiber support for ruby1.9 2010-11-17 07:42:51 +01:00
roberto@sirius 0bd017f722 fixed plugin initialization 2010-11-17 05:13:42 +01:00
roberto@fiorenzo 5a738fba8a i am afraid that ruby will never run on uGreen, time to pass to fibers 2010-11-16 17:53:15 +01:00
roberto@fiorenzo 856fd8b00f towards a better uGreen (with ruby support) 2010-11-16 10:06:19 +01:00
roberto@mrspurr d60d90afe3 various uGreen fixes 2010-11-15 21:55:55 +01:00
roberto@mrspurr 0132c00f41 fix after_request 2010-11-15 18:34:04 +01:00
roberto@mrspurr aebc637f2b new async example 2010-11-15 14:00:09 +01:00
roberto@fiorenzo d4c4643ddc YAML config file support 2010-11-14 20:20:41 +01:00
roberto@mrspurr aea66427f1 various fixes for magic options and new --remap-modifier 2010-11-14 07:18:49 +01:00
roberto@mrspurr 0376c804f9 reintroduced magic configuration 2010-11-13 20:09:54 +01:00
roberto@nexenta32 4a99069a4e NexentaOS is officially supported 2010-11-13 08:36:41 +01:00
roberto@freebsd64 e3bbcc5c84 freebsd notes for JVM 2010-11-13 08:03:01 +01:00
roberto@freebsd64 6fc40077be FreeBSD fixes 2010-11-13 07:04:51 +01:00
roberto@longshot 040d1a9d0b new amazing option: --upload-progress 2010-11-12 08:28:11 +01:00
roberto@longshot 8a121ada9d various fixes 2010-11-12 05:45:37 +01:00
roberto@mrspurr 373c45c7d4 use symlinks to automagically load plugins 2010-11-12 04:08:50 +01:00
roberto@mrspurr 3e7992d0ac added perl embedded module 2010-11-08 18:14:36 +01:00
roberto@fiorenzo 4a4455cd16 fixed jvm/jwsgi compilation on Linux 2010-11-08 16:38:44 +01:00
roberto@mrspurr 444e8d2637 utest.java, jwsgi example 2010-11-08 16:21:42 +01:00
roberto@mrspurr bcd6f7de32 jwsgi fake protocol support, better JVM api 2010-11-08 15:58:06 +01:00
roberto@mrspurr 5346ca68f9 added JVM core plugin 2010-11-07 09:15:20 +01:00
roberto@mrspurr ab83b1c7aa fixed psgi compilation 2010-11-06 08:13:46 +01:00
roberto@fiorenzo bc0eec51b4 PSGI streaming support. WebGUI is running pretty well 2010-11-05 16:02:18 +01:00
roberto@sirius 187100f2bf uwsgi.opt dictionary 2010-11-04 17:52:38 +01:00
roberto@sirius 2e4e23f63f merge 2010-11-03 19:34:55 +01:00
roberto@sirius 6f1f990f69 threads support for perl 2010-11-03 19:34:08 +01:00
roberto@mrspurr.local 75d2109254 added wt.join() in urack.rb 2010-11-03 07:35:25 +01:00
roberto@mrspurr cada9ed520 add threads support in urack.rb 2010-11-03 07:08:34 +01:00
roberto@sirius 6f3fe261d0 added buildconf/psgi.ini 2010-11-01 20:42:35 +01:00
roberto@sirius c78c0a2798 PSGI fixes 2010-11-01 18:14:38 +01:00
roberto@sirius 6249c25411 various virtual hosting fixes 2010-11-01 08:53:20 +01:00
roberto@shadowcat 36fc098c5d various ruby 1.9 fixes 2010-10-31 08:06:36 +01:00
roberto@haiku 070e84125a a bunch of haiku fixes 2010-10-29 19:34:22 +00:00
roberto@sirius aa50669237 python, ping and nagio are embedded by default 2010-10-29 13:53:05 +02:00
roberto@sirius 32ab7e79ca python fixes and optimizations 2010-10-29 13:02:59 +02:00
roberto@sirius 8971539550 pluginize ugreen and nagios 2010-10-29 10:36:58 +02:00
roberto@sirius df52dfd31f uwsgi.h vacuum 2010-10-29 08:14:03 +02:00
roberto@sirius 61756d45a2 even erlang.c was accidentally removed 2010-10-29 08:05:05 +02:00
roberto@sirius fe7a5eb5d3 reintroduce accidentally-removed mod_uwsgi.c 2010-10-29 07:47:16 +02:00
roberto@sirius e744d36fa0 investigating ruby 1.9 fiber and pluggable uWSGI loop 2010-10-28 09:25:31 +02:00
roberto@sirius 2108c85f7e trying to map ruby1.9 pthreads in uWSGI pthreads 2010-10-27 08:48:21 +02:00
roberto@mrspurr e2c405fe02 merge 2010-10-26 06:44:45 +02:00
roberto@sirius 8668b9a614 applied Dan Loewenherz stylish patch 2010-10-26 06:43:40 +02:00
roberto@fiorenzo 87ae9d780e ruby1.9 support 2010-10-25 20:11:40 +02:00
roberto@fiorenzo d0c071e759 pyargv fixes 2010-10-25 08:59:50 +02:00
roberto@fiorenzo 1a6324e825 python24, python27, python20, python31, python32 plugins 2010-10-25 08:51:52 +02:00
roberto@sirius bee3ba73d8 python25, python26 plugins 2010-10-25 08:47:31 +02:00
roberto@sirius 8dde9c2984 multiple python plugin version with the same server core 2010-10-25 08:34:10 +02:00
roberto@sirius 094d4128dc lua sputnik test with threads 2010-10-24 22:05:42 +02:00
roberto@sirius da25f77326 report correct response size in Lua plugin 2010-10-24 12:52:09 +02:00
roberto@sirius c5073f7056 Lua support improvement 2010-10-24 12:28:43 +02:00
roberto@sirius c461d2e6b3 lua plugin ported to the new api 2010-10-24 08:28:47 +02:00
roberto@sirius 6adca06764 fixed python embedded module, first refactoring of the spooler, better rack compliance 2010-10-23 21:59:43 +02:00
roberto@fiorenzo 746f645e6c disable LDAP by default even on rack plugin 2010-10-23 13:19:49 +02:00
roberto@fiorenzo e6ef84bb4b disable LDAP by default 2010-10-23 13:18:44 +02:00
roberto@sirius 17975acb45 modular buildconf 2010-10-23 13:11:13 +02:00
roberto@fiorenzo 4b81ff61eb fix plugins loading 2010-10-23 08:48:41 +02:00
roberto@fiorenzo bf868ff636 build system improvements 2010-10-23 08:44:22 +02:00
roberto@mrspurr c777a0f926 support for rack to_path and ruby GC frequency. Now Radiant works too 2010-10-23 08:41:50 +02:00
roberto@fiorenzo 7a7f499f63 Typo 5 is working \!\!\! 2010-10-22 23:12:28 +02:00
roberto@sirius b22b46b153 another bunch of rails fixes 2010-10-22 21:26:12 +02:00
roberto@sirius bbd8ea51c0 better ruby plugin, we are near to a beta version 2010-10-22 18:40:22 +02:00
roberto@sirius e1969d92ab python and ping plugins now embedded by default 2010-10-21 22:35:38 +02:00
roberto@fiorenzo e8e8b6902c fix compilation on Linux 2010-10-21 16:26:51 +02:00
roberto@sirius 7041a9fa45 xml parsing and pluginized getopt_long stabilization 2010-10-21 11:45:49 +02:00
roberto@sirius bfbca5bc96 ping plugin 2010-10-20 21:56:51 +02:00
roberto@sirius be183bf07f add new files to the tree 2010-10-20 21:55:37 +02:00
roberto@sirius f7aa451af4 uWSGI is now language agnostic, all can be pluginized, python included 2010-10-20 21:54:19 +02:00
roberto@sirius 53ccd3d4b8 new option --http-modifer1 2010-10-17 12:25:50 +02:00
roberto@sirius aaa6033c2a --log-sendfile 2010-10-16 09:09:54 +02:00
roberto@sirius 345c8ed962 another PSGI fixes round 2010-10-14 15:37:01 +02:00
roberto@sirius 9e0c7a3bdc updated PSGI plugin for 0.9.7-dev 2010-10-14 11:43:02 +02:00
Riccardo Magliocchetti 616ed04c79 Show spooler jobs in django admin 2010-10-13 11:00:22 +02:00
roberto@mrspurr 441fb06129 uwsgi.post_fork_hook 2010-10-13 07:17:00 +02:00
roberto@fiorenzo 4b92ba5cbe dynamic apps are now supported in threaded modes 2010-10-12 09:18:36 +02:00
roberto@mrspurr 13932641e5 pthread_atfork() 2010-10-12 08:23:37 +02:00
roberto@sirius 85752ccf2c add pthread locking for init_uwsgi_app 2010-10-12 07:59:37 +02:00
roberto@mrspurr 6d9b753735 various pyloaders fixes 2010-10-11 15:00:15 +02:00
roberto@fedora32 6b7e3a6429 better (race-condition-free) request counters 2010-10-10 07:48:05 +02:00
roberto@fedora32 6ef043c40a reduce GIL impact on yielding apps 2010-10-09 19:20:50 +02:00
roberto@mrspurr 9704abd3e4 apache2 right socket RST handling 2010-10-09 11:27:02 +02:00
roberto@sirius 723acced71 --close-on-exec option 2010-10-06 12:16:15 +02:00
roberto@mrspurr ca43ad0a91 various stabilization fixes 2010-10-05 05:48:20 +02:00
roberto@fiorenzo 17e2dbf85b renamed async_switches to switches 2010-10-04 17:51:22 +02:00
roberto@fiorenzo 7e40c902e6 various threading fixes 2010-10-04 17:24:59 +02:00
roberto@fiorenzo 074d0b95d1 theading support improvements 2010-10-04 14:01:56 +02:00
roberto@mrspurr 36c8a8c675 initial threading mode support 2010-10-03 22:49:22 +02:00
roberto@mrspurr 00a70c2ea2 new 0.9.7 codebase for app loading is complete 2010-10-02 18:34:55 +02:00
roberto@sirius 2bf20631e1 stabilization fixes 2010-10-01 11:50:00 +02:00
roberto 74b9579531 2 new loaders LOADER_CALLABLE and LOADER_STRING_CALLABLE 2010-10-01 10:02:46 +02:00
roberto@sirius 5a152d1bae another big loader refactoring 2010-10-01 07:45:33 +02:00
roberto@sirius 551152ade9 new loader refactoring 2010-09-30 18:13:40 +02:00
roberto@sirius 42c5b356f5 add a note to add dynamic loaders 2010-09-30 14:10:24 +02:00
roberto@sirius 33bd68c44c compilation fix 2010-09-30 14:08:05 +02:00
roberto@sirius 46b715fcc3 first merge from 0.9.6.5 (headers management still missing) 2010-09-29 08:46:38 +02:00
roberto@mrspurr b004168401 automagic recognition of the last parameter by extension 2010-09-28 07:08:04 +02:00
roberto@fiorenzo 6cebf19468 fix --wsgi-file and --pythonpath cooperation 2010-09-27 17:05:58 +02:00
roberto@mrspurr fb73324d25 more code refactoring 2010-09-26 12:17:04 +02:00
roberto@mrspurr 94624c7e52 another one destructive commit, move master to dedicated file 2010-09-26 09:11:57 +02:00
roberto@fiorenzo c4033a5970 http fix 2010-09-25 09:16:44 +02:00
roberto@fiorenzo e66e56b593 get_linux_tcp_info() refactoring 2010-09-25 08:24:16 +02:00
roberto@fiorenzo b408423b03 conditional logging 2010-09-25 08:09:34 +02:00
roberto@fiorenzo c37a2d7842 advanced socket binding and system reloading, need optimizations for single socket 2010-09-24 20:48:52 +02:00
roberto@mrspurr da339bb3a9 remove profiler 2010-09-19 09:56:14 +02:00
roberto@mrspurr f30be82926 First destructive commit for 0.9.7, big python loaders refactoring 2010-09-18 16:41:03 +02:00
roberto@mrspurr f04aa843ff fix argument count check 2010-09-18 08:41:16 +02:00
roberto@fiorenzo 5c42c27cd4 the master process will signal the overload of the listen queue on linux tcp sockets 2010-09-17 10:31:58 +02:00
roberto@fiorenzo fc744f5719 another cgroup fix 2010-09-16 19:09:24 +02:00
roberto@fiorenzo 855c963fb3 working cgroup support 2010-09-16 18:39:33 +02:00
roberto@fiorenzo dd932b0a78 OK. The Web3 test app works 2010-09-16 09:40:33 +02:00
roberto@fiorenzo e4e75a4d64 merge 2010-09-16 09:03:12 +02:00
roberto@fiorenzo ef0464dba6 Web3 support 2010-09-16 09:01:41 +02:00
roberto@fiorenzo bc2b49c8e8 uWSGI 0.9.7-dev started. Cgroup support and initial Web3 support 2010-09-16 09:00:32 +02:00
roberto@sirius 409ce34a0b uWSGI 0.9.6.2 2010-09-15 09:18:02 +02:00
roberto@sirius 89158b0509 better virtual host mode 2010-09-14 17:54:33 +02:00
roberto@sirius 86b90b8b16 fix a regression in PYTHONPATH management under INI/PASTE 2010-09-14 15:14:08 +02:00
roberto@sirius fe4c88c1c5 uWSGI 0.9.6.1 2010-09-12 09:26:54 +02:00
roberto@sirius f0f08728ab more verbose callable loading error 2010-09-12 08:57:43 +02:00
roberto@mrspurr 5259c803e8 dynamic app optimizations 2010-09-12 08:38:43 +02:00
roberto@haiku c6e5e533fa memory_report for Haiku 2010-09-12 07:41:52 +00:00
roberto@sirius 21e4cc19c8 export x-wsgiorg.uwsgi.version in WSGI env 2010-09-11 17:40:52 +02:00
roberto@haiku 045001fd6c fix Haiku usage of AF_UNIX 2010-09-11 16:17:11 +00:00
roberto@sirius eadaf3407a build system fixes 2010-09-11 14:51:51 +02:00
roberto@haiku 7434d3113c Haiku OS and gcc 2.95 support 2010-09-11 14:49:02 +00:00
roberto@sirius ab9fade14d fix no-strict-aliasing 2010-09-10 20:46:19 +02:00
roberto@sirius 5be63b02e8 fixed a typo 2010-09-10 17:25:34 +02:00
roberto@sirius 7694c38021 less verbose on SNMP management 2010-09-10 17:21:14 +02:00
roberto@sirius d13f7a45b9 ready for 0.9.6.1 2010-09-10 17:04:34 +02:00
roberto@sirius 44e8f01671 log request on SIGPIPE and HARAKIRI 2010-09-10 15:47:58 +02:00
roberto@sirius 09a8104256 protocol parsing optimization 2010-09-10 13:31:24 +02:00
roberto@fiorenzo 09d8ac2656 encoding fixes in uwsgiconfig.py 2010-09-10 11:48:11 +02:00
roberto@mrspurr c5877df60c fix --logto usage in cherokee 2010-09-10 08:35:34 +02:00
roberto@sirius 0f2fff31ee new --eval config option 2010-09-09 14:06:51 +02:00
roberto@sirius ebcdd294aa allow --pp as --pythonpath 2010-09-09 11:59:15 +02:00
roberto@sirius d663e10584 add -fno-strict-aliasing only for python 2.x or gcc < 4.3 2010-09-08 18:20:31 +02:00
roberto@sirius 048299e1d3 new spooler optimizations 2010-09-08 17:18:52 +02:00
roberto@sirius 96aaa9fa3f spooler fixes and uwsgi.spooler_jobs() 2010-09-08 17:00:32 +02:00
roberto@netbsd 015f17192c fix another strict check 2010-09-08 12:24:44 +02:00
roberto@silente f0ac801ecd support gcc < 4 2010-06-23 23:15:47 +02:00
roberto@fiorenzo f3b207c024 get return value of write() in http.c 2010-09-08 09:47:57 +02:00
roberto@freebsd64 0379e200b6 -O2 is now officially supported 2010-09-08 09:43:53 +02:00
roberto@voldemort abe6168bc3 uwsgi.is_a_reload 2010-09-07 12:27:38 +02:00
roberto@voldemort a6aa2c31c6 fixed PASTE=False compilation 2010-09-07 10:01:34 +02:00
roberto@voldemort f35ad319cf other 'c strict' fixes 2010-09-06 09:03:42 +02:00
riccardo@montag 527ad44463 fix osx compilation 2010-09-05 14:00:55 +02:00
riccardo@montag b245307f55 stricter compiler flags 2010-09-05 13:58:24 +02:00
roberto 9285b403d9 SNMP test 2010-09-05 12:47:21 +02:00
roberto@voldemort 58b72a4c80 another subprocess fix 2010-09-05 11:51:50 +02:00
roberto@sirius 73f706723e better handling of subprocesses 2010-09-03 15:46:33 +02:00
roberto@sirius 4d22f7171f fix a little comment 2010-09-03 12:20:11 +02:00
roberto@sirius b60e22b4e5 default fallback for unknown SCRIPT_NAME 2010-09-03 12:19:27 +02:00
roberto@sirius 7310b73289 fixed stupid bug in INI parsing 2010-09-03 08:14:17 +02:00
roberto@sirius 4fa61c225a uWSGI 0.9.6 2010-08-29 06:51:52 +02:00
roberto@sirius 63b41856e5 Changelog for 0.9.6 2010-08-28 19:58:55 +02:00
roberto@sirius ed1e668240 NetBSD latest fixes. Ready for 0.9.6 release 2010-08-28 19:36:55 +02:00
roberto@freebsd64 e3a7e70180 fix pidfile on HTTP mode 2010-08-28 13:51:38 +02:00
roberto@freebsd64 9f0b20c8d2 use getsockname() in vacuum() 2010-08-28 13:16:22 +02:00
roberto@freebsd64 68aff372ce HTTP final fixes, better reloading system, better cwd detection, powered up vacuum 2010-08-28 13:00:21 +02:00
roberto@sirius 38cfa72318 close ini file 2010-08-27 11:07:35 +02:00
roberto@sirius 31047e1e10 fixes for --file and shebang support 2010-08-27 07:32:44 +02:00
roberto@sirius bbb90296bb applied Leonid Borisenko patch to allow -O2 and -fno-strict-aliasing CFLAGS 2010-08-27 06:21:43 +02:00
roberto@sirius 00c6aa2f65 0.9.6-rc2 2010-08-26 17:08:15 +02:00
roberto@sirius 720da09631 xmlconf fixes 2010-08-26 15:33:25 +02:00
roberto@fiorenzo 47f7c09b97 add empty QUERY_STRING in http server 2010-08-26 14:55:39 +02:00
roberto@sirius cb5704da10 --callable 2010-08-26 14:09:15 +02:00
roberto@fiorenzo c64356b231 uwsgi packet watermark in HTTP server 2010-08-26 11:38:48 +02:00
roberto@sirius 2acd2f5224 another solaris hack 2010-08-26 11:01:57 +02:00
roberto@sirius ba251f8e3d another solaris fix 2010-08-26 10:09:40 +02:00
roberto@sirius 48019f9044 first round of http fixes 2010-08-26 10:06:17 +02:00
roberto@sunsparc d9a1f2448c solaris fixes 2010-08-26 09:33:23 +02:00
roberto@ubuntu64 553a947c2d fix routing 2010-08-26 08:43:28 +02:00
roberto@sirius 736aedfa89 add --ini-paste commodity and removal of strlc* functions 2010-08-26 08:36:44 +02:00
roberto@sirius 6184acc727 updated --help 2010-08-25 20:00:10 +02:00
roberto@sirius f0d96b03fa added --ping and --ping-timeout 2010-08-25 19:21:31 +02:00
roberto@sirius 14bf840eef fix urack.rb upload 2010-08-24 16:44:32 +02:00
roberto@sirius 7ea08093c7 uWSGI 0.9.6-rc1 2010-08-24 08:41:25 +02:00
roberto@sirius 8eb8d07151 ready for rc1 ? 2010-08-24 08:37:24 +02:00
roberto@sirius cdd95b434e http and sendfile fix 2010-08-24 08:33:03 +02:00
roberto@ubuntu64 82cbcea886 Linux has no strlcat 2010-08-23 18:51:02 +02:00
roberto@silente ea54a05fc3 OpenBSD fixes by Piotr Sikora 2010-06-08 07:43:48 +02:00
roberto@ubuntu64 eba39dcd67 LDAP support 2010-08-23 14:27:49 +02:00
roberto@ubuntu64 d71ea1404d allow non-numeric uid and gid 2010-08-22 18:31:18 +02:00
roberto@ubuntu64 0f0d5b2a5f safer automatic unix socket and --vacuum option 2010-08-22 18:02:09 +02:00
roberto@mrspurr 10a75ef848 support key-only value (without '=') in ini files 2010-08-22 08:10:23 +02:00
roberto@sirius 4bd9bf8917 remove REMOTE_USER in http server 2010-08-19 08:16:42 +02:00
roberto@mrspurr 323da1299e another fix for PEP 333 file_wrapper compatiblity 2010-08-18 19:42:21 +02:00
roberto@mrspurr 75d08898b4 http server fixes 2010-08-18 16:37:10 +02:00
roberto@sirius 5e47796a02 something to fix in utf8 handling [2] 2010-08-17 14:13:04 +02:00
roberto@sirius 0ade5aba0a something to fix in utf8 handling 2010-08-17 14:12:52 +02:00
roberto@sirius f7b1ad8cb0 add a little comment 2010-08-17 14:10:52 +02:00
roberto@sirius 3bd147e687 fixed random seeding (thanks to Jonas Borgström) 2010-08-17 14:04:44 +02:00
roberto@voldemort 66c99e257f fix pidfile (will be written at server startup and only if it is not a reload) 2010-08-15 18:55:48 +02:00
roberto@voldemort 8407a5921b warn user about harakiri without post buffering 2010-08-15 18:52:20 +02:00
roberto@voldemort 5f36987827 applied Jonas Borgström patch for lighttpd REMOTE_USER 2010-08-15 18:40:09 +02:00
roberto@voldemort ede1622368 fix a stupid bug in apache module 2010-08-14 15:59:36 +02:00
roberto@voldemort a28dfb790e does a fix for not reading post data really exists ? 2010-08-14 08:17:33 +02:00
roberto@voldemort 3711cbbd61 ini file improvement 2010-08-14 08:13:04 +02:00
roberto@voldermort c9ef6281ff added --catch-exceptions, it will print app exceptions to your browser 2010-08-13 17:37:34 +02:00
roberto@voldemort 604ea6fd57 INI files support 2010-08-13 15:46:37 +02:00
roberto@longshot 41dfcaa705 added --chdir2 2010-08-11 17:35:14 +02:00
roberto@sirius daa41d4a51 fixed --unbit PYLIB_PATH 2010-08-11 09:20:22 +02:00
roberto@sirius ded4450a70 http build option 2010-08-11 09:18:50 +02:00
roberto@sirius cd0be56bbe fixed --unbit 2010-08-11 08:59:12 +02:00
roberto@sirius 0bf7b64b46 mjpeg streaming example using uwsgi.sendfile() 2010-08-08 15:43:24 +02:00
roberto@sirius 215d2e7055 full PEP 333 compliant file_wrapper and advanced uwsgi.sendfile() 2010-08-08 15:41:34 +02:00
roberto@voldemort 2b5b0cf1bc fix spooler stdin 2010-08-05 12:21:34 +02:00
roberto@voldemort 67231da4a9 added uwsgi.env 2010-08-03 18:03:34 +02:00
roberto@sirius 8c25b38470 fix UNBIT compilation 2010-07-29 10:19:06 +02:00
roberto@sirius 08bbe0cd30 MINTERPRETERS build fixes 2010-07-28 14:37:47 +02:00
roberto@sirius 9f9f63fe2f UDP build fixes 2010-07-28 14:31:58 +02:00
roberto@sirius 997bd63cc3 add LD_RUN_PATH option 2010-07-27 11:43:22 +02:00
roberto@siris 6a566d9dca fix static compilation 2010-07-27 11:40:54 +02:00
roberto@sirius d2e743a800 rack/rails plugin base added. NOT USABLE 2010-07-27 08:47:27 +02:00
roberto@sirius 2fedb175b4 disable WSGI2 flag by default 2010-07-21 11:02:18 +02:00
roberto@sirius 6c5e25dbfe sendfile fix 2010-07-20 17:56:54 +02:00
roberto@fiorenzo 94fd3f0bfd mega.xml example 2010-07-20 15:45:19 +02:00
roberto@fiorenzo ca169b05fb xml id, working multi-thread http server, --env support 2010-07-20 15:43:09 +02:00
roberto@voldemort 10ea1fee6e a bunch of fixes 2010-07-19 12:22:16 +02:00
roberto@sirius d7b8704165 conditional paste inclusion and django_admin fix 2010-07-14 16:34:56 +02:00
roberto@voldemort 0f774b840c quick_callable, --chdir and (broken) multithread http.c 2010-07-14 00:19:00 +02:00
roberto@sirius 81521a314b embedded HTTP server for easy development 2010-07-12 18:34:16 +02:00
roberto@sirius 37ee7f8908 better management of SCRIPT_NAME 2010-07-07 11:47:39 +02:00
roberto@sirius 309648f68b more verbose spooler 2010-07-06 10:44:00 +02:00
roberto@sirius 5cfa65d04e Python 2.7 support 2010-07-06 09:20:41 +02:00
roberto@voldemort e73c8194a0 64 bit fixes [2] 2010-06-28 10:37:46 +02:00
roberto@voldemort 00a3f6ae7f 64 bit fixes 2010-06-28 10:36:02 +02:00
roberto@voldemort b7edaa68c8 various fixes from 0.9.5.2 2010-06-26 22:37:46 +02:00
roberto@sirius 2877ba54de better routing 2010-06-23 19:55:41 +02:00
roberto@mrspurr f74a19a71a preliminary routing support (PCRE needed) 2010-06-21 17:42:03 +02:00
roberto@sirius 3da5238ee5 PSGI embedded support 2010-06-14 16:59:50 +02:00
roberto@fedora-arm 567dd36592 remove UGREEN on arm 2010-06-11 02:48:53 -04:00
roberto@sirius b48062a026 add 0x to hex debug printing 2010-06-10 08:34:02 +02:00
roberto@sirius b039cb713f VirtualHosting mode and UWSGI_PYHOME uwsgi var 2010-06-10 08:05:11 +02:00
roberto@sirius 8e987ffa18 proposed WSGI2.0 response support 2010-06-08 17:44:43 +02:00
roberto@mrspurr 52502342e0 fix copyright year 2010-06-03 12:59:48 +02:00
roberto@mrspurr cb9e3c22f9 added apache2 mod_Ruwsgi 2010-06-03 12:53:27 +02:00
roberto@sirius 0c465775ad force next_upstream on http_502 and http_504 on nginx 2010-06-03 08:08:28 +02:00
roberto@sirius a5417f4963 Davies Liu fix for protocol parsing 2010-06-03 08:01:34 +02:00
roberto@mrspurr b48076f6e4 support for 'grunt' processes 2010-05-31 14:06:42 +02:00
roberto@voldemort c472eae332 upstart contrib example 2010-05-22 06:54:23 +02:00
roberto@voldemort 918fc654f4 --no-orphans option (uses prctl on Linux and getppid on others) 2010-05-22 06:39:09 +02:00
roberto@voldemort 9097cbe10d 0.9.5.1 tag 2010-05-19 16:09:08 +02:00
roberto@sirius e260873338 uWSGI 0.9.5.1 2010-05-19 16:08:29 +02:00
roberto@voldemort a7822742c0 lighttpd PATH_INFO fix 2010-05-18 08:01:32 +02:00
roberto@voldemort f1316ef4bb fix env configuration 2010-05-18 07:34:36 +02:00
roberto@sirius 4106931175 fix getrlimit() 2010-05-18 07:06:07 +02:00
roberto@sirius fb5ba40f0c support for unladen swallow 2010-05-16 12:34:19 +02:00
roberto@sirius 854e51f0ad fix for eval modifier 2010-05-13 13:47:15 +02:00
roberto@sirium 676b43f17d UWSGI_MODIFIER_EVAL and nginx module update 2010-05-13 13:04:37 +02:00
roberto@sirius 48b68e6a92 updated help and version 2010-05-12 16:40:47 +02:00
roberto@sirius 61f33721e1 add --limit-post 2010-05-12 13:13:01 +02:00
roberto@sirius 5c3c46598f --post-buffering, this will help harakiri mode with big uploads 2010-05-12 12:54:49 +02:00
roberto@sirius 4358036f9e add --prio option 2010-05-12 09:10:04 +02:00
roberto@sirius 54d75d92ef fix paste support 2010-05-10 18:04:01 +02:00
roberto@sirius b1ae57c932 applied gentoo fixes 2010-05-10 10:58:52 +02:00
roberto@sirius 2636baa33f added --logto 2010-05-02 12:38:39 +02:00
roberto@sirius 926c739517 0.9.5 2010-05-01 08:24:21 +02:00
roberto@sirius 79fa25c4e0 latest (i hope) pip hack 2010-05-01 08:10:36 +02:00
roberto@sirius 02050675a8 pip hack [5] 2010-05-01 08:06:44 +02:00
roberto@sirius 0d5857a1bc pip hack [4] 2010-05-01 08:04:05 +02:00
roberto@sirius e3a51be1f9 pip hack [3] 2010-05-01 07:58:53 +02:00
roberto@sirius 57cb098a6e move to setuptools 2010-05-01 07:39:56 +02:00
roberto@sirius 5f285eef56 pip hack [2] 2010-05-01 07:29:07 +02:00
roberto@sirius 7d5cf6f318 pip hack 2010-05-01 07:14:14 +02:00
roberto@silente 99d305c7a1 snmp big endian fixes 2010-04-30 16:41:57 +02:00
roberto@sirius b9cc3b6a7d snmp fix 2010-04-30 15:51:32 +02:00
roberto@sirius e1f8c69d3d minor fixes 2010-04-30 15:16:18 +02:00
roberto@sirius 67b6fbd15b admin modifier fix 2010-04-30 14:46:27 +02:00
roberto@sirius 50f407eb9e no_server fix 2010-04-30 14:41:30 +02:00
roberto@freebsd b127699c0a FreeBSD/Dragonfly little fix 2010-04-30 14:12:51 +02:00
roberto@netbsd 4d74fa6759 small netbsd include fix 2010-04-30 16:04:02 +02:00
roberto@sirius 2b9d6cb7c2 uwsgi_log everywhere 2010-04-30 12:28:01 +02:00
roberto@solaris e0b67bba58 uwsgi_log instead of fprintf [1] 2010-04-30 12:22:07 +02:00
roberto@silente 3cdf17df75 strlcopy insted of strcpy 2010-04-30 09:54:25 +02:00
roberto@silente 43c086494b be more verbose on extreme cases 2010-04-30 09:18:53 +02:00
roberto@silente ae26e90b3a OpenBSD ha no RLIMIT_AS and swapcontext(), added an harakiri message to avoid user confusion 2010-04-30 09:01:26 +02:00
roberto@sirius d35a7d8725 updated urack.rb for unbit 2010-04-27 12:47:29 +02:00
roberto@sirius 043e7ddde4 uWSGI 0.9.5-rc2 2010-04-20 10:51:54 +02:00
226 changed files with 34087 additions and 10060 deletions
+18
View File
@@ -1,3 +1,21 @@
d3850b52334a91d005b0fe45e1e38ba0997a1fb8 no_server mode
2d8a617299153ed2efa6ecee7920e9d36c29e0f5 0.9.5beta1
04722a2d0121080d14a64df097c278860db5ce8a 0.9.5rc1
820cc64ab296dc4589ef72a33a6b804c22a0430c 0.9.5rc2
b0db39cfad5ac6d4f00bbb3f9c57cf73206e2afb 0.9.5
9f8b98ad1dfa51b86b13fa624c65f73523075fc4 0.9.5.1
a83e7a482e65befcfbb0e24af8cd5d15190acdd7 0.9.6-rc1
b8f67c6cd0d62f864db9b2b265b4e260ad7d873c 0.9.6-rc2
35918dd4b3771158b2b57410613ef029e08bbd60 0.9.6
5f25d1f97f9dde3e391a668c1c610a52a5db8244 0.9.6.1
ef31fc61ac48018c464f28ebfdf865b96bf83f18 0.9.6.2
9e100c1f085034396cec586f0c76ad3f9800d1a5 0.9.7-beta1
ff4111eb8f55b958ec91c70163e10f3372a9b94d 0.9.7-rc1
eb8aff2926230bb114fb90f67203440a2c534bf1 0.9.7-rc2
311eef929ec8fd0a5dc8c16531afb7bb42d36d01 0.9.7-rc3
4b50c04e414f1d9ab8b0b5910aba83d09ac21abb 0.9.7
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
0000000000000000000000000000000000000000 0.9.7.1
0000000000000000000000000000000000000000 0.9.7.1
486e7760bcbc2191ddb9b4aee6c98dbd5fc4c754 0.9.7.1
+302
View File
@@ -1,3 +1,305 @@
*** april 2011 ***
* 0.9.7.2 [20110406]
- new option --touch-reload <file> to reload the stack on <file> modification
--static-map <mountpoint=documentroot> allows to serve static files
- fixed --post-limit management
- disallow empty socket names
- implemented exception_info WSGI support
- new options --reload-on-as <n> and --reload-on-rss <n> allows
to recycle workers when their memory usage is higher than <n> MB
- fixed syslog support (use --log-syslog[=facility] to enable it)
- improved plugin loading system
- added support for RabbitMQ as event dispatcher for the Emperor
- fixed FreeBSD memory report
- PSGI plugin can be compiled without ithreads
- various Emperor fixes
- fixed a regression with setgroups()
- support for shared sockets (used in jails within network namespaces)
*** march 2011 ***
* 0.9.7.1 [20110326]
- fixed python stackless support
- added persistence for queue
- forbid daemonizing in vassal mode
- modifier1 30 is available again
- allow python modules to be mapped/aliased via http
- added --pidfile2 and --logfile-chown
- added UWSGI_CACHE_GET dynamic variable
- 304/If-Modified-Since support for --check-static
- option --check-cache for integrated caching
- option --map-socket to assign specific workers to socket
- fixed unix fd passing on older OSX versions
- fixed post-buffering without pep3333-input
- fixed python threading without uwsgi cores
- support for Linux network namespace
- build with sys.abiflags if necessary
* 0.9.7 [20110317]
- fixed psgi compilation on GNU systems
- improved --pep3333-input
- better error reporting on failed open/fopen
- fixed uGreen
- added greenlet support
- various solaris fixes
- new help system
- updated async support
- fixed uwsgi.cache_get in python
* 0.9.7-rc3 [20110312]
- added support for persistent cache (--cache-store <filename>)
- less verbose file monitoring
- fixed a race condition in emperor startup
- fixed erlang empty list encoding
- improved snmp support
- fixed cache modifier 111 for 3 and 4
- preliminary cpu-affinity support (Linux only)
- fixed ldap support
- auto-configure ldap compilation
- added --allowed-modifiers (allow only a subset of modifiers)
- fixed a bug with getopt_long
* 0.9.7-rc2 [20110309]
- added cron-like interface to signal framework
- improved Linux namespaces support
- fixed multithreading + --max-requests
- added support for reference in configuration files
* 0.9.7-rc1 [20110307]
- export %v in emperor mode
- fixed signal race condition in server reload
- fixed http router post handling bug
- added uwsgi.erlang_register_process in pyerl plugin
- fixed unix socket inherit
- fixed linux namespace support in recent kernel/gcc
- ported threading to python 3.2
- add build date to uWSGI startup info
- do not allow clustering without defining a socket
- kill all the gateways/daemons on startup errors
- fixed vacuum after chdir()
- fixed gateways reload
- re-added support for OpenBSD and NetBSD
- fixed post-buffering in python
- use erlang binary for python string
- fixed memory leak in pyerl plugin
- removed broken log rotation (post-poned)
- fixed no_argument options in ini and yaml parsing
* 0.9.7-beta1 [20110301]
- fully modular re-design
- advanced build system with presets
- threading support
- emperor mode for massive auto-hosting
- caching subsystem
- message queue (even stacked) support
- improved server reloading system
- support for Linux Cgroups and Namespaces
- integrated upload progress
- Clustering infrastructure via multicast, broadcast or subscriptions
- support for attaching/monitoring external apps to the master process
- improved virtualhosting mode
- extremely improved Python support with better usage of multiple interpreters
- improved multiple apps support
- Production ready, evented HTTP router/proxy/load-balancer
- Production ready, evented uwsgi router/proxy/load-balancer
- new Erlang stack
- Internal signal subsystem
- support for RubyOnRails and Rack apps
- A huge series of fixes and optimizations
*** february 2011 ***
* 0.9.6.8 [20110207]
- fixed a bug when using --limit-as
- fixed a erlang buffer initialization
- added --ignore-sigpipe
- added --master-as-root
*** january 2011 ***
* 0.9.6.7 [20110130]
- a huge amount of async optimizations and fixes
- --logdate takes an optional strftime-like value
- follow $PATH on reloading
- uwsgi.core is exported in WSGI env
- uwsgi.log() respect for --logdate
- initial banner respect for --logdate
- fixed --post-buffering
- default listen backlog queue is now 100
- Python 3 support is no more marked as experimental
- Python 3.2 support
- new option --chroot-reload will force a reload of the uWSGI stack after a chroot
- fixed a typo in INI parsing
*** december 2010 ***
* 0.9.6.6 [20101230]
- support for YAML configuration files
- backported python module aliasing from 0.9.7-dev
- better apache2 module (support for SetEnv directive, fixed REQUEST_URI and improved connection handling)
- uwsgi.post_fork_hook implementation (to execute function after fork()) (thanks George Kollias)
- option --gid calls setgroups() after setgid() (thanks Jorge Cardona)
- fixed uGreen compilation (and uGreen is now built by default)
- fixed timeout and thundering herd problem in async modes (many thanks to Test157 for giving us a good async-test-app)
- disable TCP_INFO in older Linux kernels (thanks Bo Shi)
- enable TCP_INFO in FreeBSD (limited usage due to FreeBSD kernel support)
- fixed static virtualhosting mode using xml files (thanks Guido Notari of Link I.T. spa)
- new option --close-on-exec (thanks Jean-Baptiste Quenot)
- use HTTP_HOST var (and fallback to SERVER_NAME) in virtual hosting mode
- fixed a buffer overflow in automatic socket_name allocation (spotted by Riccardo Magliocchetti)
- Official support for Nexenta
*** september 2010 ***
* 0.9.6.5 [20100929]
- PEP 3333 support
- fix --pythonpath with --wsgi-file
- x-wsgiorg.uwsgi.version renamed to uwsgi.version
* 0.9.6.4 [20100925]
- fix a stupid bug in conditional logging backport
* 0.9.6.3 [20100925]
- fix a buffer overflow in .ini parsing (it throws a glibc error on malloc)
- backport of conditional logging from 0.9.7-dev
- backport of backlog queue monitor from 0.9.7-dev (only Linux)
* 0.9.6.2 [20100915]
- fix a regression in virtual hosting mode
- fix pythonpath usage in --ini and --ini-paste
- new uwsgi packet var: UWSGI_CHDIR
* 0.9.6.1 [20100912]
- print the request uri during SIGPIPE or HARAKIRI
- added SIGUSR2 support (it will print the current running request, if available)
- protocol parsing optimization
- fixed --logto support
- new --eval option allows inline definition of WSGI script
- support for defining WSGI script in xml using CDATA
- allow --pp as --pythonpath shortcut
- various spooler optimizations and fixes
- added -O2 optimization by default
- added uwsgi.is_a_reload commodity function
- .ini file support fix
- SNMP agent fix
- support for subprocesses generated by master
- fix a regression in SCRIPT_NAME handling
- Haiku official support
- gcc 2.95 support
- dynamic app management optimizations
- export x-wsgiorg.uwsgi.version in WSGI env
*** august 2010 ***
* 0.9.6 [20100829]
- better handling of SCRIPT_NAME
- vacuum option for deleting unix sockets and pidfiles after usage
- advanced XML configuration
- new configuration systems: INI files and LDAP
- embedded HTTP server for development/testing
- better signal handling
- PSGI plugin improved
- usability fixes and new commodities options for root startup
- grunt processes (detached workers)
- preliminary integrated virtualhosting mode
- new option catch-exceptions can redirect python exceptions to your browser
- logging improvements (--logto and --logdate options)
- Full PEP 333 compliant usage of wsgi.file_wrapper
- re-initialize random seed after every fork() [security fix]
- fix Spooler's usage of stdin
- export WSGI environment in uwsgi.env (for doing evil things)
- logsize tracking (uwsgi.logsize) for future embedded log rotation
*** july 2010 ***
* 0.9.5.4 [20100706]
*** june 2010 ***
* 0.9.5.3 [20100628]
- fixed linux x86_64 compilation (sorry)
* 0.9.5.2 [20100626] *
- fixed a request parsing bug
- applied debian fixes
- fixed multiple interpreter sys.argv
- improved --chmod-socket
- fixed uid 0 SIGHUP
- updated nginx and apache modules
- updated PSGI, lua and example plugin
- fixed --pyargv with python 3.x
- improved plugin build system
*** may 2010 ***
* 0.9.5.1 [20100519] *
- fixed paste support
- added a new modifier (22)
- full support for configuration via environment variables
- nginx_string option in nginx module
- fix for harakiri without master
- backported unladen swallow support for 0.9.6-dev
- fixed address space limit detection via getrlimit()
- http body buffering implementation
- added --prio option (to set priority)
- added --post-limit to limit the size of uploads
- added --logto option to allow udp logging without daemonizing
- applied Gentoo's packagers fixes for build system
* 0.9.5 [20100501] *
- hook based request/modifier management
- plugin support via dlopen
- on-the-fly management flag
- integrated proxy
- logging via udp
- improved spooler for cron-like apps
- async support
- green thread platform (uGreen) on top of the async mode
- transparent Erlang integration
- embedded snmp agent
- nagios mode
- improved python 3.x support
- improved xml configuration
- new build system
- address space usage limiting
- lot of portability fixes
- lot of optimizations and code refactoring
*** april 2010 ***
* Fourth Maintenance release [20100427] *
- backported non-yielding app optimization from 0.9.5
- backported udp logging from 0.9.5
- backported uwsgi_error() from 0.9.5 (no more dumb perror())
- fix a rare (but possible) segmentation fault
- added --version
- updated apache2 module
*** march 2010 ***
* Third Maintenance release [20100310] *
+2
View File
@@ -0,0 +1,2 @@
all:
python2.7 uwsgiconfig.py --build
+2
View File
@@ -0,0 +1,2 @@
all:
python3.2 uwsgiconfig.py --build
+2
View File
@@ -0,0 +1,2 @@
all:
python uwsgiconfig.py --build pylua
+923
View File
@@ -0,0 +1,923 @@
/*
*** uWSGI/mod_Ruwsgi ***
Copyright 2009-2010 Roger Florkowski <rflorkowski@mypublisher.com>
Copyright 2009-2010 Unbit S.a.s. <info@unbit.it>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#define MOD_UWSGI_VERSION "1.0"
#include "ap_config.h"
#include "apr_version.h"
#include "apr_lib.h"
#include "apr_strings.h"
#include "httpd.h"
#include "http_core.h"
#include "http_request.h"
#include "http_config.h"
#include "http_log.h"
#include "http_protocol.h"
#include "util_script.h"
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/uio.h>
#include <time.h>
#include <poll.h>
#define DEFAULT_TIMEOUT 60 /* default socket timeout */
#define DEFAULT_CGIMODE 0 /* not enabled */
#define UNSET 0
#define ENABLED 1
#define DISABLED 2
#if APR_MAJOR_VERSION == 0
#define apr_socket_send apr_send
#define GET_PORT(port, addr) apr_sockaddr_port_get(&(port), addr)
#define CREATE_SOCKET(sock, family, pool) \
apr_socket_create(sock, family, SOCK_STREAM, pool)
#else
#define GET_PORT(port, addr) ((port) = (addr)->port)
#define CREATE_SOCKET(sock, family, pool) \
apr_socket_create(sock, family, SOCK_STREAM, APR_PROTO_TCP, pool)
#endif
typedef struct {
char *path;
char *addr;
apr_port_t port;
} mount_entry;
/*
* Configuration record. Used per-directory configuration data.
*/
typedef struct {
mount_entry mount;
int enabled; /* mod_uwsgi is enabled from this directory */
int timeout;
int cgi_mode;
uint8_t modifier1;
uint8_t modifier2;
} uwsgi_cfg;
/* Server level configuration */
typedef struct {
apr_array_header_t *mounts;
int timeout;
int cgi_mode;
} uwsgi_server_cfg;
module AP_MODULE_DECLARE_DATA uwsgi_module;
/*
* Locate our directory configuration record for the current request.
*/
static uwsgi_cfg *
our_dconfig(request_rec *r)
{
return (uwsgi_cfg *) ap_get_module_config(r->per_dir_config, &uwsgi_module);
}
static uwsgi_server_cfg *our_sconfig(server_rec *s)
{
return (uwsgi_server_cfg *) ap_get_module_config(s->module_config,
&uwsgi_module);
}
static int
mount_entry_matches(const char *url, const char *prefix,
const char **path_info)
{
int i;
for (i=0; prefix[i] != '\0'; i++) {
if (url[i] == '\0' || url[i] != prefix[i])
return 0;
}
if (url[i] == '\0' || url[i] == '/') {
*path_info = url + i;
return 1;
}
return 0;
}
static int uwsgi_translate(request_rec *r)
{
uwsgi_cfg *cfg = our_dconfig(r);
if (cfg->enabled == DISABLED) {
return DECLINED;
}
if (cfg->mount.addr != UNSET) {
ap_assert(cfg->mount.port != UNSET);
r->handler = "uwsgi-handler";
r->filename = r->uri;
return OK;
}
else {
int i;
uwsgi_server_cfg *scfg = our_sconfig(r->server);
mount_entry *entries = (mount_entry *) scfg->mounts->elts;
for (i = 0; i < scfg->mounts->nelts; ++i) {
const char *path_info;
mount_entry *mount = &entries[i];
if (mount_entry_matches(r->uri, mount->path, &path_info)) {
r->handler = "uwsgi-handler";
r->path_info = apr_pstrdup(r->pool, path_info);
r->filename = r->uri;
ap_set_module_config(r->request_config, &uwsgi_module, mount);
return OK;
}
}
}
return DECLINED;
}
static int uwsgi_map_location(request_rec *r)
{
if (r->handler && strcmp(r->handler, "uwsgi-handler") == 0) {
return OK; /* We don't want directory walk. */
}
return DECLINED;
}
static void log_err(const char *file, int line, request_rec *r,
apr_status_t status, const char *msg)
{
ap_log_rerror(file, line, APLOG_ERR, status, r, "uwsgi: %s", msg);
}
static void log_debug(const char *file, int line, request_rec *r, const
char *msg)
{
/*
ap_log_rerror(file, line, APLOG_DEBUG, APR_SUCCESS, r, msg);
ap_log_rerror(file, line, APLOG_WARNING, APR_SUCCESS, r, "uwsgi: %s", msg);
*/
ap_log_rerror(file, line, APLOG_DEBUG, APR_SUCCESS, r, "uwsgi: %s", msg);
}
/* buffered socket implementation (buckets are overkill) */
#define BUFFER_SIZE 8000
struct sockbuff {
apr_socket_t *sock;
char buf[BUFFER_SIZE];
int used;
};
static void binit(struct sockbuff *s, apr_socket_t *sock)
{
s->sock = sock;
s->used = 0;
}
static apr_status_t sendall(apr_socket_t *sock, char *buf, apr_size_t len)
{
apr_status_t rv;
apr_size_t n;
while (len > 0) {
n = len;
if ((rv = apr_socket_send(sock, buf, &n))) return rv;
buf += n;
len -= n;
}
return APR_SUCCESS;
}
static apr_status_t bflush(struct sockbuff *s)
{
apr_status_t rv;
ap_assert(s->used >= 0 && s->used <= BUFFER_SIZE);
if (s->used) {
if ((rv = sendall(s->sock, s->buf, s->used))) return rv;
s->used = 0;
}
return APR_SUCCESS;
}
static apr_status_t bwrite(struct sockbuff *s, char *buf, apr_size_t len)
{
apr_status_t rv;
if (len >= BUFFER_SIZE - s->used) {
if ((rv = bflush(s))) return rv;
while (len >= BUFFER_SIZE) {
if ((rv = sendall(s->sock, buf, BUFFER_SIZE))) return rv;
buf += BUFFER_SIZE;
len -= BUFFER_SIZE;
}
}
if (len > 0) {
ap_assert(len < BUFFER_SIZE - s->used);
memcpy(s->buf + s->used, buf, len);
s->used += len;
}
return APR_SUCCESS;
}
static apr_status_t bputs(struct sockbuff *s, char *buf)
{
return bwrite(s, buf, strlen(buf));
}
static apr_status_t bputc(struct sockbuff *s, char c)
{
char buf[1];
buf[0] = c;
return bwrite(s, buf, 1);
}
static apr_status_t bputh(struct sockbuff *s, unsigned short h)
{
return bwrite(s, (char *)&h, 2);
}
#define CONFIG_VALUE(value, fallback) ((value) != UNSET ? (value) : (fallback))
static apr_status_t
open_socket(apr_socket_t **sock, request_rec *r)
{
int timeout;
int retries = 4;
int sleeptime = 1;
apr_status_t rv;
apr_sockaddr_t *sockaddr;
uwsgi_server_cfg *scfg = our_sconfig(r->server);
uwsgi_cfg *cfg = our_dconfig(r);
mount_entry *m = (mount_entry *) ap_get_module_config(r->request_config,
&uwsgi_module);
if (!m) {
m = &cfg->mount;
}
timeout = CONFIG_VALUE(cfg->timeout, CONFIG_VALUE(scfg->timeout,
DEFAULT_TIMEOUT));
rv = apr_sockaddr_info_get(&sockaddr,
CONFIG_VALUE(m->addr, "localhost"),
APR_UNSPEC,
CONFIG_VALUE(m->port, 5000),
0,
r->pool);
if (rv) {
log_err(APLOG_MARK, r, rv, "apr_sockaddr_info_get() error");
return rv;
}
restart:
*sock = NULL;
rv = CREATE_SOCKET(sock, sockaddr->family, r->pool);
if (rv) {
log_err(APLOG_MARK, r, rv, "apr_socket_create() error");
return rv;
}
rv = apr_socket_timeout_set(*sock, apr_time_from_sec(timeout));
if (rv) {
log_err(APLOG_MARK, r, rv, "apr_socket_timeout_set() error");
return rv;
}
rv = apr_socket_connect(*sock, sockaddr);
if (rv) {
apr_socket_close(*sock);
if ((APR_STATUS_IS_ECONNREFUSED(rv) |
APR_STATUS_IS_EINPROGRESS(rv)) && retries > 0) {
/* server may be temporarily down, retry */
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, rv, r,
"uwsgi: connection failed, retrying");
apr_sleep(apr_time_from_sec(sleeptime));
--retries;
sleeptime *= 2;
goto restart;
}
log_err(APLOG_MARK, r, rv, "uwsgi: can't connect to server");
return rv;
}
#ifdef APR_TCP_NODELAY
/* disable Nagle, we don't send small packets */
apr_socket_opt_set(*sock, APR_TCP_NODELAY, 1);
#endif
return APR_SUCCESS;
}
/* This code is a duplicate of what's in util_script.c. We can't use
* r->unparsed_uri because it gets changed if there was a redirect. */
static char *original_uri(request_rec *r)
{
char *first, *last;
if (r->the_request == NULL) {
return (char *) apr_pcalloc(r->pool, 1);
}
first = r->the_request; /* use the request-line */
while (*first && !apr_isspace(*first)) {
++first; /* skip over the method */
}
while (apr_isspace(*first)) {
++first; /* and the space(s) */
}
last = first;
while (*last && !apr_isspace(*last)) {
++last; /* end at next whitespace */
}
return apr_pstrmemdup(r->pool, first, last - first);
}
static char *lookup_name(apr_table_t *t, const char *name)
{
const apr_array_header_t *hdrs_arr = apr_table_elts(t);
apr_table_entry_t *hdrs = (apr_table_entry_t *) hdrs_arr->elts;
int i;
for (i = 0; i < hdrs_arr->nelts; ++i) {
if (hdrs[i].key == NULL)
continue;
if (strcasecmp(hdrs[i].key, name) == 0)
return hdrs[i].val;
}
return NULL;
}
static char *lookup_header(request_rec *r, const char *name)
{
return lookup_name(r->headers_in, name);
}
static void add_header(apr_table_t *t, const char *name, const char *value)
{
if (name != NULL && value != NULL)
apr_table_addn(t, name, value);
}
static int find_path_info(const char *uri, const char *path_info)
{
int n;
n = strlen(uri) - strlen(path_info);
ap_assert(n >= 0);
return n;
}
static char *http2env(apr_pool_t *p, const char *name)
{
char *env_name = apr_pstrcat(p, "HTTP_", name, NULL);
char *cp;
for (cp = env_name + 5; *cp != 0; cp++) {
if (*cp == '-') {
*cp = '_';
}
else {
*cp = apr_toupper(*cp);
}
}
return env_name;
}
static apr_status_t
send_headers(request_rec *r, struct sockbuff *s)
{
int i;
const apr_array_header_t *hdrs_arr, *env_arr;
apr_table_entry_t *hdrs, *env;
char *buf;
unsigned short int n = 0;
apr_table_t *t;
apr_status_t rv = 0;
apr_port_t port = 0;
GET_PORT(port, r->connection->remote_addr);
uwsgi_cfg *cfg = our_dconfig(r);
log_debug(APLOG_MARK,r, "sending headers");
t = apr_table_make(r->pool, 40);
if (!t)
return APR_ENOMEM;
/* headers to send */
/* CONTENT_LENGTH must come first and always be present */
buf = lookup_header(r, "Content-Length");
if (buf == NULL)
buf = "0";
add_header(t, "CONTENT_LENGTH", buf);
add_header(t, "REQUEST_METHOD", (char *) r->method);
add_header(t, "QUERY_STRING", r->args ? r->args : "");
add_header(t, "SERVER_SOFTWARE", ap_get_server_version());
add_header(t, "SERVER_ADMIN", r->server->server_admin);
add_header(t, "SERVER_NAME", (char *) ap_get_server_name(r));
add_header(t, "SERVER_PORT", apr_psprintf(r->pool, "%u",ap_get_server_port(r)));
add_header(t, "SERVER_ADDR", r->connection->local_ip);
add_header(t, "SERVER_PROTOCOL", r->protocol);
add_header(t, "REQUEST_URI", original_uri(r));
add_header(t, "REMOTE_ADDR", r->connection->remote_ip);
add_header(t, "REMOTE_PORT", apr_psprintf(r->pool, "%d", port));
add_header(t, "REMOTE_USER", r->user);
add_header(t, "DOCUMENT_ROOT", (char *) ap_document_root(r));
if (r->path_info) {
int path_info_start = find_path_info(r->uri, r->path_info);
add_header(t, "SCRIPT_NAME", apr_pstrndup(r->pool, r->uri,
path_info_start));
add_header(t, "PATH_INFO", r->path_info);
}
else {
/* skip PATH_INFO, don't know it */
add_header(t, "SCRIPT_NAME", r->uri);
}
add_header(t, "CONTENT_TYPE", lookup_header(r, "Content-type"));
/* HTTP headers */
hdrs_arr = apr_table_elts(r->headers_in);
hdrs = (apr_table_entry_t *) hdrs_arr->elts;
for (i = 0; i < hdrs_arr->nelts; ++i) {
if (hdrs[i].key) {
add_header(t, http2env(r->pool, hdrs[i].key), hdrs[i].val);
}
}
/* environment variables */
env_arr = apr_table_elts(r->subprocess_env);
env = (apr_table_entry_t*) env_arr->elts;
for (i = 0; i < env_arr->nelts; ++i) {
add_header(t, env[i].key, env[i].val);
}
hdrs_arr = apr_table_elts(t);
hdrs = (apr_table_entry_t*) hdrs_arr->elts;
/* calculate length of header data */
for (i = 0; i < hdrs_arr->nelts; ++i) {
n += strlen(hdrs[i].key);
n += strlen(hdrs[i].val);
n += 4; /* XXX */
}
log_debug(APLOG_MARK,r, apr_psprintf(r->pool, "pktheader size is %u", n));
log_debug(APLOG_MARK,r, apr_psprintf(r->pool, "num headers %u", hdrs_arr->nelts));
/* write pkt header */
rv = bputc(s, cfg->modifier1); /* marker */
if (rv) return rv;
rv = bputh(s, n); /* length of header data */
if (rv) return rv;
rv = bputc(s, cfg->modifier2); /* marker */
if (rv) return rv;
/* write out headers */
for (i = 0; i < hdrs_arr->nelts; ++i) {
rv = bputh(s, strlen(hdrs[i].key)); /* length */
if (rv) return rv;
rv = bputs(s, hdrs[i].key); /* key */
if (rv) return rv;
rv = bputh(s, strlen(hdrs[i].val)); /* length */
if (rv) return rv;
rv = bputs(s, hdrs[i].val); /* data */
if (rv) return rv;
}
return APR_SUCCESS;
}
static apr_status_t send_request_body(request_rec *r, struct sockbuff *s)
{
if (ap_should_client_block(r)) {
char buf[BUFFER_SIZE];
apr_status_t rv;
apr_off_t len;
while ((len = ap_get_client_block(r, buf, sizeof buf)) > 0) {
if ((rv = bwrite(s, buf, len))) return rv;
}
if (len == -1)
return HTTP_INTERNAL_SERVER_ERROR; /* what to return? */
}
return APR_SUCCESS;
}
static int uwsgi_handler(request_rec *r)
{
apr_status_t rv = 0;
int cgi_mode, http_status = 0;
struct sockbuff s;
apr_socket_t *sock;
apr_bucket_brigade *bb = NULL;
apr_bucket *b = NULL;
const char *location;
uwsgi_cfg *cfg = our_dconfig(r);
uwsgi_server_cfg *scfg = our_sconfig(r->server);
if (strcmp(r->handler, "uwsgi-handler"))
return DECLINED;
http_status = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR);
if (http_status != OK)
return http_status;
log_debug(APLOG_MARK, r, "connecting to server");
rv = open_socket(&sock, r);
if (rv) {
return HTTP_INTERNAL_SERVER_ERROR;
}
binit(&s, sock);
rv = send_headers(r, &s);
if (rv) {
log_err(APLOG_MARK, r, rv, "error sending request headers");
return HTTP_INTERNAL_SERVER_ERROR;
}
rv = send_request_body(r, &s);
if (rv) {
log_err(APLOG_MARK, r, rv, "error sending request body");
return HTTP_INTERNAL_SERVER_ERROR;
}
rv = bflush(&s);
if (rv) {
log_err(APLOG_MARK, r, rv, "error sending request");
return HTTP_INTERNAL_SERVER_ERROR;
}
log_debug(APLOG_MARK, r, "reading response headers");
bb = apr_brigade_create(r->connection->pool, r->connection->bucket_alloc);
cgi_mode = CONFIG_VALUE(cfg->cgi_mode, CONFIG_VALUE(scfg->cgi_mode, DEFAULT_CGIMODE));
if (!cgi_mode) {
/* receive implemented with http-0.9 based protocol */
apr_interval_time_t timeout;
char buf[4096];
apr_pollfd_t pollfd = {r->pool, APR_POLL_SOCKET, APR_POLLIN, 0, { NULL }, NULL };
pollfd.desc.s = sock;
timeout = CONFIG_VALUE(cfg->timeout, CONFIG_VALUE(scfg->timeout,
DEFAULT_TIMEOUT)) * 1000 * 1000;
r->assbackwards = 1; /* XXX */
for(;;) {
apr_int32_t nsds;
apr_size_t len;
if ((rv = apr_poll(&pollfd, 1, &nsds, timeout)) == APR_TIMEUP) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() timeout");
break;
}
if (rv != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: poll() %s", strerror(errno));
break;
}
len = 4096;
rv = apr_socket_recv(sock, buf, &len);
if (rv == APR_SUCCESS) {
apr_brigade_write(bb, NULL, NULL, buf, len);
}
else if (rv == APR_EOF) {
break;
}
else {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() %s", strerror(errno));
}
}
log_debug(APLOG_MARK,r, "recv finished");
b = apr_bucket_flush_create(r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
b = apr_bucket_eos_create(r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
} else {
/* receive implemented with http-1.x based protocol */
b = apr_bucket_socket_create(sock, r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
b = apr_bucket_eos_create(r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
rv = ap_scan_script_header_err_brigade(r, bb, NULL);
if (rv) {
if (rv == HTTP_INTERNAL_SERVER_ERROR) {
log_err(APLOG_MARK, r, rv, "error reading response headers");
}
else {
/* Work around an Apache bug whereby the returned status is
* ignored and status_line is used instead. This bug is
* present at least in 2.0.54.
*/
r->status_line = NULL;
}
apr_brigade_destroy(bb);
return rv;
}
location = apr_table_get(r->headers_out, "Location");
if (location && location[0] == '/' &&
((r->status == HTTP_OK) || ap_is_HTTP_REDIRECT(r->status))) {
apr_brigade_destroy(bb);
/* Internal redirect -- fake-up a pseudo-request */
r->status = HTTP_OK;
/* This redirect needs to be a GET no matter what the original
* method was.
*/
r->method = apr_pstrdup(r->pool, "GET");
r->method_number = M_GET;
ap_internal_redirect_handler(location, r);
return OK;
}
}
rv = ap_pass_brigade(r->output_filters, bb);
if (rv) {
log_err(APLOG_MARK, r, rv, "ap_pass_brigade()");
return HTTP_INTERNAL_SERVER_ERROR;
}
return OK;
}
static int uwsgi_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
server_rec *base_server)
{
ap_add_version_component(p, "mod_uwsgi/" MOD_UWSGI_VERSION);
return OK;
}
static void *
uwsgi_create_dir_config(apr_pool_t *p, char *dirspec)
{
uwsgi_cfg *cfg = apr_pcalloc(p, sizeof(uwsgi_cfg));
cfg->enabled = UNSET;
cfg->mount.addr = UNSET;
cfg->mount.port = UNSET;
cfg->timeout = UNSET;
cfg->cgi_mode = UNSET;
cfg->modifier1 = UNSET;
cfg->modifier2 = UNSET;
return cfg;
}
#define MERGE(b, n, a) (n->a == UNSET ? b->a : n->a)
static void *
uwsgi_merge_dir_config(apr_pool_t *p, void *basev, void *newv)
{
uwsgi_cfg* cfg = apr_pcalloc(p, sizeof(uwsgi_cfg));
uwsgi_cfg* base = basev;
uwsgi_cfg* new = newv;
cfg->enabled = MERGE(base, new, enabled);
cfg->mount.addr = MERGE(base, new, mount.addr);
cfg->mount.port = MERGE(base, new, mount.port);
cfg->timeout = MERGE(base, new, timeout);
cfg->cgi_mode = MERGE(base, new, cgi_mode);
cfg->modifier1 = MERGE(base, new, modifier1);
cfg->modifier2 = MERGE(base, new, modifier2);
return cfg;
}
static void *
uwsgi_create_server_config(apr_pool_t *p, server_rec *s)
{
uwsgi_server_cfg *c =
(uwsgi_server_cfg *) apr_pcalloc(p, sizeof(uwsgi_server_cfg));
c->mounts = apr_array_make(p, 20, sizeof(mount_entry));
c->timeout = UNSET;
c->cgi_mode = UNSET;
return c;
}
static void *
uwsgi_merge_server_config(apr_pool_t *p, void *basev, void *overridesv)
{
uwsgi_server_cfg *c = (uwsgi_server_cfg *)
apr_pcalloc(p, sizeof(uwsgi_server_cfg));
uwsgi_server_cfg *base = (uwsgi_server_cfg *) basev;
uwsgi_server_cfg *overrides = (uwsgi_server_cfg *) overridesv;
c->mounts = apr_array_append(p, overrides->mounts, base->mounts);
c->timeout = MERGE(base, overrides, timeout);
c->cgi_mode = MERGE(base, overrides, cgi_mode);
return c;
}
static const char *
cmd_uwsgi_mount(cmd_parms *cmd, void *dummy, const char *path, const char *addr)
{
int n;
apr_status_t rv;
char *scope_id = NULL; /* A ip6 parameter - not used here. */
uwsgi_server_cfg *scfg = our_sconfig(cmd->server);
mount_entry *new = apr_array_push(scfg->mounts);
n = strlen(path);
while (n > 0 && path[n-1] == '/') {
n--; /* strip trailing slashes */
}
new->path = apr_pstrndup(cmd->pool, path, n);
rv = apr_parse_addr_port(&new->addr, &scope_id, &new->port, addr,
cmd->pool);
if (rv)
return "error parsing address:port string";
return NULL;
}
static const char *
cmd_uwsgi_server(cmd_parms *cmd, void *pcfg, const char *addr_and_port)
{
apr_status_t rv;
uwsgi_cfg *cfg = pcfg;
char *scope_id = NULL; /* A ip6 parameter - not used here. */
if (cmd->path == NULL)
return "not a server command";
rv = apr_parse_addr_port(&cfg->mount.addr, &scope_id, &cfg->mount.port,
addr_and_port, cmd->pool);
if (rv)
return "error parsing address:port string";
return NULL;
}
static const char *
cmd_uwsgi_handler(cmd_parms* cmd, void* pcfg, int flag)
{
uwsgi_cfg *cfg = pcfg;
if (cmd->path == NULL) /* server command */
return "not a server command";
if (flag)
cfg->enabled = ENABLED;
else
cfg->enabled = DISABLED;
return NULL;
}
static const char *
cmd_uwsgi_timeout(cmd_parms *cmd, void* pcfg, const char *strtimeout)
{
uwsgi_cfg *dcfg = pcfg;
int timeout = atoi(strtimeout);
if (cmd->path == NULL) {
uwsgi_server_cfg *scfg = our_sconfig(cmd->server);
scfg->timeout = timeout;
}
else {
dcfg->timeout = timeout;
}
return NULL;
}
static const char *
cmd_uwsgi_force_cgi_mode(cmd_parms *cmd, void *pcfg, const char *value)
{
int cgi_mode;
if (!strcmp("yes", value) || !strcmp("on", value) || !strcmp("enable", value) || !strcmp("1", value)) {
cgi_mode = 1;
}
else {
cgi_mode = 0;
}
if (cmd->path == NULL) {
uwsgi_server_cfg *scfg = our_sconfig(cmd->server);
scfg->cgi_mode = cgi_mode;
}
else {
uwsgi_cfg *dcfg = pcfg;
dcfg->cgi_mode = cgi_mode;
}
return NULL;
}
static const char *
cmd_uwsgi_modifier1(cmd_parms *cmd, void *pcfg, const char *value)
{
uwsgi_cfg *cfg = pcfg;
int val;
if (cmd->path == NULL) /* server command */
return "not a server command";
val = atoi(value);
if (val < 0 || val > 255) {
return "ignored uWSGImodifier1. Value must be between 0 and 255";
}
else {
cfg->modifier1 = (uint8_t) val;
}
return NULL;
}
static const char *
cmd_uwsgi_modifier2(cmd_parms *cmd, void *pcfg, const char *value)
{
uwsgi_cfg *cfg = pcfg;
int val;
if (cmd->path == NULL) /* server command */
return "not a server command";
val = atoi(value);
if (val < 0 || val > 255) {
return "ignored uWSGImodifier2. Value must be between 0 and 255";
}
else {
cfg->modifier2 = (uint8_t) val;
}
return NULL;
}
static const command_rec uwsgi_cmds[] = {
AP_INIT_TAKE2("uWSGImount", cmd_uwsgi_mount, NULL, RSRC_CONF,
"path prefix and address of UWSGI server"),
AP_INIT_TAKE1("uWSGIserver", cmd_uwsgi_server, NULL, ACCESS_CONF,
"Address and port of an UWSGI server (e.g. localhost:4000)"),
AP_INIT_FLAG( "uWSGIhandler", cmd_uwsgi_handler, NULL, ACCESS_CONF,
"On or Off to enable or disable the UWSGI handler"),
AP_INIT_TAKE1("uWSGIserverTimeout", cmd_uwsgi_timeout, NULL, ACCESS_CONF|RSRC_CONF,
"Timeout (in seconds) for communication with the UWSGI server."),
AP_INIT_TAKE1("uWSGIforceCGImode", cmd_uwsgi_force_cgi_mode, NULL, ACCESS_CONF|RSRC_CONF,
"Force uWSGI CGI mode for perfect integration with apache filter"),
AP_INIT_TAKE1("uWSGImodifier1", cmd_uwsgi_modifier1, NULL, ACCESS_CONF,
"Set uWSGI modifier1"),
AP_INIT_TAKE1("uWSGImodifier2", cmd_uwsgi_modifier2, NULL, ACCESS_CONF,
"Set uWSGI modifier2"),
/*
AP_INIT_TAKE12("uWSGIsocket", cmd_uwsgi_socket, NULL, RSRC_CONF|ACCESS_CONF,
"Absolute path and optional timeout in seconds of uwsgi server socket"),
AP_INIT_TAKE1("uWSGIsocket2", cmd_uwsgi_socket2, NULL, RSRC_CONF|ACCESS_CONF,
"Absolute path of failover uwsgi server socket"),
AP_INIT_TAKE1("uWSGIforceScriptName", cmd_uwsgi_force_script_name, NULL, ACCESS_CONF,
"Fix for PATH_INFO/SCRIPT_NAME when the location has filesystem correspondence"),
*/
{NULL}
};
static void uwsgi_register_hooks(apr_pool_t *p)
{
ap_hook_post_config(uwsgi_init, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_handler(uwsgi_handler, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_translate_name(uwsgi_translate, NULL, NULL, APR_HOOK_LAST);
ap_hook_map_to_storage(uwsgi_map_location, NULL, NULL, APR_HOOK_FIRST);
}
/* Dispatch list for API hooks */
module AP_MODULE_DECLARE_DATA uwsgi_module = {
STANDARD20_MODULE_STUFF,
uwsgi_create_dir_config, /* create per-dir config structs */
uwsgi_merge_dir_config, /* merge per-dir config structs */
uwsgi_create_server_config, /* create per-server config structs */
uwsgi_merge_server_config, /* merge per-server config structs */
uwsgi_cmds, /* table of config file commands */
uwsgi_register_hooks, /* register hooks */
};
+61 -37
View File
@@ -1,18 +1,18 @@
/*
*** uWSGI/mod_uwsgi ***
*** uWSGI/mod_uwsgi ***
Copyright 2009 Unbit S.a.s. <info@unbit.it>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
Copyright 2009-2010 Unbit S.a.s. <info@unbit.it>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
@@ -264,7 +264,6 @@ static int uwsgi_handler(request_rec *r) {
char uwsgi_http_status[13] ;
int uwsgi_http_status_read = 0;
apr_bucket_brigade *bb;
if (strcmp(r->handler, "uwsgi-handler"))
@@ -287,7 +286,6 @@ static int uwsgi_handler(request_rec *r) {
return HTTP_INTERNAL_SERVER_ERROR;
}
if ( (ret = timed_connect(&uwsgi_poll, (struct sockaddr *) &c->s_addr, c->addr_size, c->socket_timeout, r) ) != 0) {
close(uwsgi_poll.fd);
@@ -323,7 +321,7 @@ static int uwsgi_handler(request_rec *r) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SERVER_NAME", (char *) ap_get_server_name(r), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SERVER_PORT", apr_psprintf(r->pool, "%u",ap_get_server_port(r)), &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SERVER_PROTOCOL", r->protocol, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REQUEST_URI", r->uri, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REQUEST_URI", r->unparsed_uri, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REMOTE_ADDR", r->connection->remote_ip, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REMOTE_USER", r->user ? r->user : "", &pkt_size) ;
if (r->user) {
@@ -394,6 +392,13 @@ static int uwsgi_handler(request_rec *r) {
}
}
}
/* environment variables */
headers = apr_table_elts(r->subprocess_env);
h = (apr_table_entry_t*) headers->elts;
for (i = 0; i < headers->nelts; ++i) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, h[i].key, h[i].val, &pkt_size) ;
}
uwsgi_vars[0].iov_base = pkt_header;
@@ -456,33 +461,52 @@ static int uwsgi_handler(request_rec *r) {
return HTTP_INTERNAL_SERVER_ERROR;
}
else if (cnt > 0) {
cnt = recv(uwsgi_poll.fd, buf, 4096, 0) ;
if (cnt < 0) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() %s", strerror(errno));
apr_brigade_destroy(bb);
return HTTP_INTERNAL_SERVER_ERROR;
}
else if (cnt > 0) {
if (!c->cgi_mode && uwsgi_http_status_read < 12) {
if (uwsgi_http_status_read + cnt >= 12) {
memcpy(uwsgi_http_status+uwsgi_http_status_read, buf, 12-uwsgi_http_status_read);
r->status = atoi(uwsgi_http_status+8);
uwsgi_http_status_read+=cnt;
}
else {
memcpy(uwsgi_http_status+uwsgi_http_status_read, buf, cnt);
uwsgi_http_status_read+=cnt;
}
}
apr_brigade_write(bb, NULL, NULL, buf, cnt);
}
else {
break;
if (uwsgi_poll.revents & POLLIN || uwsgi_poll.revents & POLLHUP) {
cnt = recv(uwsgi_poll.fd, buf, 4096, 0) ;
if (cnt < 0) {
if (errno != ECONNRESET) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() %s", strerror(errno));
apr_brigade_destroy(bb);
return HTTP_INTERNAL_SERVER_ERROR;
}
else {
break;
}
}
else if (cnt > 0) {
if (!c->cgi_mode && uwsgi_http_status_read < 12) {
if (uwsgi_http_status_read + cnt >= 12) {
memcpy(uwsgi_http_status+uwsgi_http_status_read, buf, 12-uwsgi_http_status_read);
r->status = atoi(uwsgi_http_status+8);
uwsgi_http_status_read+=cnt;
}
else {
memcpy(uwsgi_http_status+uwsgi_http_status_read, buf, cnt);
uwsgi_http_status_read+=cnt;
}
}
// check for client disconnect
if (r->connection->aborted) {
close(uwsgi_poll.fd);
apr_brigade_destroy(bb);
return HTTP_INTERNAL_SERVER_ERROR;
}
apr_brigade_write(bb, NULL, NULL, buf, cnt);
}
else {
// EOF
break;
}
}
// error
if (uwsgi_poll.revents & POLLERR || uwsgi_poll.revents & POLLNVAL) {
break;
}
}
else {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: poll() %s", strerror(errno));
close(uwsgi_poll.fd);
apr_brigade_destroy(bb);
return HTTP_INTERNAL_SERVER_ERROR;
}
+310 -400
View File
@@ -1,459 +1,369 @@
#ifdef UWSGI_ASYNC
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#ifdef __linux__
#include <sys/epoll.h>
int async_queue_init(int serverfd) {
int epfd ;
struct epoll_event ee;
epfd = epoll_create(256);
if (epfd < 0) {
uwsgi_error("epoll_create()");
return -1 ;
}
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = EPOLLIN;
ee.data.fd = serverfd;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, serverfd, &ee)) {
uwsgi_error("epoll_ctl()");
close(epfd);
return -1;
}
return epfd;
struct wsgi_request *find_wsgi_req_by_fd(int fd) {
return uwsgi.async_waiting_fd_table[fd];
}
int async_wait(int queuefd, void *events, int nevents, int block, int timeout) {
void runqueue_remove(struct uwsgi_async_request *u_request) {
int ret ;
struct uwsgi_async_request *parent = u_request->prev;
struct uwsgi_async_request *child = u_request->next;
if (parent) {
parent->next = child;
}
if (child) {
child->prev = parent;
}
if (timeout <= 0) {
timeout = block;
if (parent == NULL) {
uwsgi.async_runqueue = child;
}
if (u_request == uwsgi.async_runqueue_last) {
uwsgi.async_runqueue_last = parent;
}
free(u_request);
uwsgi.async_runqueue_cnt--;
}
void runqueue_push(struct wsgi_request *wsgi_req) {
struct uwsgi_async_request *uar;
if (uwsgi.async_runqueue == NULL) {
// empty runqueue, create a new one
uwsgi.async_runqueue = uwsgi_malloc(sizeof(struct uwsgi_async_request));
uwsgi.async_runqueue->next = NULL;
uwsgi.async_runqueue->prev = NULL;
uwsgi.async_runqueue->wsgi_req = wsgi_req;
uwsgi.async_runqueue_last = uwsgi.async_runqueue;
}
else {
uar = uwsgi_malloc(sizeof(struct uwsgi_async_request));
uar->prev = uwsgi.async_runqueue_last;
uar->next = NULL;
uar->wsgi_req = wsgi_req;
uwsgi.async_runqueue_last->next = uar;
uwsgi.async_runqueue_last = uar;
}
uwsgi.async_runqueue_cnt++;
}
struct wsgi_request *find_first_available_wsgi_req() {
struct wsgi_request *wsgi_req;
if (uwsgi.async_queue_unused_ptr < 0) {
return NULL;
}
wsgi_req = uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr];
uwsgi.async_queue_unused_ptr--;
return wsgi_req;
}
void async_expire_timeouts() {
struct wsgi_request *wsgi_req;
time_t current_time = time(NULL);
struct uwsgi_async_fd *uaf = NULL, *current_uaf;
struct uwsgi_rb_timer *urbt;
for(;;) {
urbt = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts);
if (urbt == NULL) return;
if (urbt->key <= current_time) {
wsgi_req = (struct wsgi_request *) urbt->data;
// timeout expired
wsgi_req->async_timed_out = 1;
rb_erase(&wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
free(wsgi_req->async_timeout);
wsgi_req->async_timeout = NULL;
uaf = wsgi_req->waiting_fds;
// remove fds from monitoring (no problem modifying the queue here, as the function is executed only when there are no fd ready)
while(uaf) {
event_queue_del_fd(uwsgi.async_queue, uaf->fd, uaf->event);
uwsgi.async_waiting_fd_table[uaf->fd] = NULL;
current_uaf = uaf;
uaf = current_uaf->next;
free(current_uaf);
}
wsgi_req->waiting_fds = NULL;
// put th request in the runqueue
runqueue_push(wsgi_req);
continue;
}
break;
}
}
void async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
if (fd < 0) return ;
// find first slot
while(uad) {
last_uad = uad;
uad = uad->next;
}
uad = uwsgi_malloc(sizeof(struct uwsgi_async_fd));
uad->fd = fd;
uad->event = event_queue_read();
uad->prev = last_uad;
uad->next = NULL;
if (last_uad) {
last_uad->next = uad;
}
else {
timeout = timeout*1000;
wsgi_req->waiting_fds = uad;
}
//fprintf(stderr,"waiting with timeout %d nevents %d\n", timeout, nevents);
ret = epoll_wait(queuefd, (struct epoll_event *) events, nevents, timeout);
if (ret < 0) {
uwsgi_error("epoll_wait()");
if (timeout > 0) {
async_add_timeout(wsgi_req, timeout);
}
return ret ;
uwsgi.async_waiting_fd_table[fd] = wsgi_req;
event_queue_add_fd_read(uwsgi.async_queue, fd);
}
int async_add(int queuefd, int fd, int etype) {
struct epoll_event ee;
void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = etype;
ee.data.fd = fd;
if (epoll_ctl(queuefd, EPOLL_CTL_ADD, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
if (timeout > 0 && wsgi_req->async_timeout == NULL) {
wsgi_req->async_timeout = uwsgi_add_rb_timer(uwsgi.rb_async_timeouts, time(NULL)+timeout, wsgi_req);
}
return 0;
}
int async_mod(int queuefd, int fd, int etype) {
struct epoll_event ee;
void async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = etype;
ee.data.fd = fd;
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
if (epoll_ctl(queuefd, EPOLL_CTL_MOD, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
if (fd < 0) return ;
// find first slot
while(uad) {
last_uad = uad;
uad = uad->next;
}
return 0;
}
uad = uwsgi_malloc(sizeof(struct uwsgi_async_fd));
uad->fd = fd;
uad->event = event_queue_write();
uad->prev = last_uad;
uad->next = NULL;
int async_del(int queuefd, int fd, int etype) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = etype;
ee.data.fd = fd;
if (epoll_ctl(queuefd, EPOLL_CTL_DEL, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
if (last_uad) {
last_uad->next = uad;
}
else {
wsgi_req->waiting_fds = uad;
}
return 0;
}
#elif defined(__sun__)
int async_queue_init(int serverfd) {
int dpfd ;
struct pollfd dpev;
dpfd = open("/dev/poll", O_RDWR);
if (dpfd < 0) {
uwsgi_error("open()");
return -1 ;
}
dpev.fd = serverfd;
dpev.events = POLLIN ;
dpev.revents = 0;
if (write(dpfd, &dpev, sizeof(struct pollfd)) < 0) {
uwsgi_error("write()");
return -1;
}
return dpfd;
}
int async_wait(int queuefd, void *events, int nevents, int block, int timeout) {
int ret ;
struct dvpoll dv ;
if (timeout <= 0) {
timeout = block;
}
else {
timeout = timeout*1000;
if (timeout > 0) {
async_add_timeout(wsgi_req, timeout);
}
dv.dp_fds = (struct pollfd *) events;
dv.dp_nfds = nevents;
dv.dp_timeout = timeout;
uwsgi.async_waiting_fd_table[fd] = wsgi_req;
event_queue_add_fd_write(uwsgi.async_queue, fd);
//fprintf(stderr,"waiting with timeout %d nevents %d\n", timeout, nevents);
ret = ioctl(queuefd, DP_POLL, &dv);
if (ret < 0) {
uwsgi_error("ioctl()");
}
return ret ;
}
int async_add(int queuefd, int fd, int etype) {
struct pollfd pl;
pl.fd = fd ;
pl.events = etype ;
pl.revents = 0 ;
if (write(queuefd, &pl, sizeof(struct pollfd)) < 0) {
uwsgi_error("write()");
return -1;
}
return 0;
void async_schedule_to_req(void) {
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->request(uwsgi.wsgi_req);
}
int async_mod(int queuefd, int fd, int etype) {
// using the same fd will overwrite existing rule
return async_add(queuefd, fd, etype);
}
void *async_loop(void *arg1) {
int async_del(int queuefd, int fd, int etype) {
// use POLLREMOVE to remove an fd
return async_add(queuefd, fd, POLLREMOVE);
}
struct uwsgi_async_fd *tmp_uaf;
int interesting_fd, i;
struct uwsgi_rb_timer *min_timeout;
int timeout;
#else
int async_queue_init(int serverfd) {
int kfd ;
struct kevent kev;
static struct uwsgi_async_request *current_request = NULL, *next_async_request = NULL;
kfd = kqueue();
void *events = event_queue_alloc(64);
if (kfd < 0) {
uwsgi_error("kqueue()");
return -1 ;
}
uwsgi.async_runqueue = NULL;
uwsgi.async_runqueue_cnt = 0;
EV_SET(&kev, serverfd, EVFILT_READ, EV_ADD, 0, 0, 0);
if (kevent(kfd, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
// set a default request manager
if (!uwsgi.schedule_to_req) uwsgi.schedule_to_req = async_schedule_to_req;
return kfd;
}
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
int async_wait(int queuefd, void *events, int nevents, int block, int timeout) {
int ret;
struct timespec ts ;
if (timeout <= 0) {
if (!block) {
memset(&ts, 0, sizeof(struct timespec));
ts.tv_sec = timeout ;
ret = kevent(queuefd, NULL, 0, events, nevents, &ts);
if (uwsgi.async_runqueue_cnt) {
timeout = 0;
}
else {
ret = kevent(queuefd, NULL, 0, events, nevents, NULL);
}
}
else {
memset(&ts, 0, sizeof(struct timespec));
ts.tv_sec = timeout ;
ret = kevent(queuefd, NULL, 0, events, nevents, &ts);
}
if (ret < 0) {
uwsgi_error("kevent()");
}
return ret;
}
int async_add(int queuefd, int fd, int etype) {
struct kevent kev;
EV_SET(&kev, fd, etype, EV_ADD, 0, 0, 0);
if (kevent(queuefd, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return 0;
}
int async_mod(int queuefd, int fd, int etype) {
struct kevent kev;
EV_SET(&kev, fd, ASYNC_OUT, EV_DISABLE, 0, 0, 0);
if (kevent(queuefd, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
EV_SET(&kev, fd, etype, EV_ADD, 0, 0, 0);
if (kevent(queuefd, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return 0;
}
int async_del(int queuefd, int fd, int etype) {
struct kevent kev;
EV_SET(&kev, fd, etype, EV_DELETE, 0, 0, 0);
if (kevent(queuefd, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return 0;
}
#endif
inline struct wsgi_request *next_wsgi_req(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
uint8_t *ptr = (uint8_t *) wsgi_req ;
ptr += sizeof(struct wsgi_request) ;
return (struct wsgi_request *) ptr ;
}
int async_get_timeout(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
time_t curtime, tdelta = 0 ;
int ret = 0 ;
if (!uwsgi->async_running) return 0;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_AGAIN) {
if (wsgi_req->async_timeout_expired) {
return 0;
min_timeout = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts);
if (uwsgi.async_runqueue_cnt) {
timeout = 0;
}
if (wsgi_req->async_timeout > 0) {
if (tdelta <= 0 || tdelta > wsgi_req->async_timeout) {
tdelta = wsgi_req->async_timeout ;
}
}
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
curtime = time(NULL);
ret = tdelta - curtime ;
if (ret > 0) {
return ret;
}
return 0;
}
void async_expire_timeouts(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
time_t deadline = time(NULL);
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_AGAIN && wsgi_req->async_timeout > 0) {
if (wsgi_req->async_timeout <= deadline) {
wsgi_req->async_timeout = 0 ;
wsgi_req->async_timeout_expired = 1 ;
}
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
}
struct wsgi_request *find_first_available_wsgi_req(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_OK) {
return wsgi_req ;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
return NULL ;
}
struct wsgi_request *find_wsgi_req_by_id(struct uwsgi_server *uwsgi, int async_id) {
uint8_t *ptr = (uint8_t *) uwsgi->wsgi_requests ;
ptr += sizeof(struct wsgi_request) * async_id ;
return (struct wsgi_request *) ptr ;
}
struct wsgi_request *find_wsgi_req_by_fd(struct uwsgi_server *uwsgi, int fd, int etype) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
if (etype != -1) {
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_waiting_fd == fd && wsgi_req->async_waiting_fd_type == etype) {
return wsgi_req ;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
}
else {
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_waiting_fd == fd) {
return wsgi_req ;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
}
return NULL ;
}
void async_set_timeout(struct wsgi_request *wsgi_req, time_t timeout) {
wsgi_req->async_timeout = time(NULL);
wsgi_req->async_timeout += timeout;
wsgi_req->async_timeout_expired = 0 ;
}
void async_write_all(struct uwsgi_server *uwsgi, char *data, size_t len) {
struct wsgi_request *wsgi_req = uwsgi->wsgi_requests ;
int i;
ssize_t rlen ;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_PAUSED) {
rlen = write(wsgi_req->poll.fd, data, len);
if (rlen < 0) {
uwsgi_error("write()");
if (min_timeout) {
timeout = min_timeout->key - time(NULL);
if (timeout <= 0) {
async_expire_timeouts();
timeout = 0;
}
}
else {
wsgi_req->response_size += rlen ;
timeout = -1;
}
}
uwsgi.async_nevents = event_queue_wait_multi(uwsgi.async_queue, timeout, events, 64);
// timeout ???
if (uwsgi.async_nevents == 0) {
async_expire_timeouts();
}
}
}
void async_unpause_all(struct uwsgi_server *uwsgi) {
struct wsgi_request *wsgi_req = uwsgi->wsgi_requests ;
int i;
for(i=0;i<uwsgi.async_nevents;i++) {
// manage events
interesting_fd = event_queue_interesting_fd(events, i);
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_PAUSED) {
wsgi_req->async_status = UWSGI_AGAIN;
}
}
}
struct wsgi_request * async_loop(struct uwsgi_server *uwsgi) {
struct wsgi_request *wsgi_req ;
int i ;
uwsgi->async_running = -1 ;
wsgi_req = uwsgi->wsgi_requests ;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_AGAIN) {
if (wsgi_req->async_waiting_fd != -1 && !wsgi_req->async_waiting_fd_monitored) {
// add fd to monitoring
if (async_add(uwsgi->async_queue, wsgi_req->async_waiting_fd, wsgi_req->async_waiting_fd_type)) {
// error adding fd to the async queue, better to close it...
close(wsgi_req->async_waiting_fd);
wsgi_req->async_status = UWSGI_OK ;
return wsgi_req;
// new request coming in
if (interesting_fd == uwsgi.sockets[0].fd) {
uwsgi.wsgi_req = find_first_available_wsgi_req();
if (uwsgi.wsgi_req == NULL) {
uwsgi_log("async queue is full !!!\n");
continue;
}
wsgi_req->async_waiting_fd_monitored = 1;
wsgi_req->async_status = UWSGI_AGAIN;
}
else if (wsgi_req->async_waiting_fd == -1 && wsgi_req->async_timeout <= 0) {
uwsgi->async_running = 0 ;
// st global wsgi_req for python functions
uwsgi->wsgi_req = wsgi_req ;
wsgi_req->async_status = (*uwsgi->shared->hooks[wsgi_req->uh.modifier1]) (uwsgi, wsgi_req);
wsgi_req->async_switches++;
if (wsgi_req->async_status < UWSGI_AGAIN) {
return wsgi_req;
wsgi_req_setup(uwsgi.wsgi_req, uwsgi.wsgi_req->async_id );
if (wsgi_req_simple_accept(uwsgi.wsgi_req, interesting_fd)) {
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(uwsgi.async_queue, interesting_fd);
#endif
continue;
}
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(uwsgi.async_queue, interesting_fd);
#endif
// on linux we do not need to reset the socket to blocking state
#ifndef __linux__
if (uwsgi.numproc > 1) {
/* re-set blocking socket */
if (fcntl(uwsgi.wsgi_req->poll.fd, F_SETFL, uwsgi.sockets[0].arg) < 0) {
uwsgi_error("fcntl()");
continue;
}
}
#endif
if (wsgi_req_simple_recv(uwsgi.wsgi_req)) {
continue;
}
// put request in the runqueue
runqueue_push(uwsgi.wsgi_req);
}
else {
// app event
uwsgi.wsgi_req = find_wsgi_req_by_fd(interesting_fd);
// unknown fd, remove it (for safety)
if (uwsgi.wsgi_req == NULL) {
close(interesting_fd);
continue;
}
// remove all the fd monitors and timeout
while(uwsgi.wsgi_req->waiting_fds) {
#ifndef UWSGI_EVENT_USE_PORT
event_queue_del_fd(uwsgi.async_queue, uwsgi.wsgi_req->waiting_fds->fd, uwsgi.wsgi_req->waiting_fds->event);
#endif
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
free(tmp_uaf);
}
uwsgi.wsgi_req->waiting_fds = NULL;
if (uwsgi.wsgi_req->async_timeout) {
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
}
uwsgi.wsgi_req->async_ready_fd = 1;
uwsgi.wsgi_req->async_last_ready_fd = interesting_fd;
// put the request in the runqueue again
runqueue_push(uwsgi.wsgi_req);
}
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
// event queue managed, give cpu to runqueue
if (!current_request)
current_request = uwsgi.async_runqueue;
if (uwsgi.async_runqueue_cnt) {
uwsgi.wsgi_req = current_request->wsgi_req;
uwsgi.schedule_to_req();
uwsgi.wsgi_req->switches++;
next_async_request = current_request->next;
// request ended ?
if (uwsgi.wsgi_req->async_status == UWSGI_OK) {
// remove all the monitored fds and timeout
while(uwsgi.wsgi_req->waiting_fds) {
#ifndef UWSGI_EVENT_USE_PORT
event_queue_del_fd(uwsgi.async_queue, uwsgi.wsgi_req->waiting_fds->fd, uwsgi.wsgi_req->waiting_fds->event);
#endif
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
free(tmp_uaf);
}
uwsgi.wsgi_req->waiting_fds = NULL;
if (uwsgi.wsgi_req->async_timeout) {
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
}
// remove from the list
runqueue_remove(current_request);
uwsgi_close_request(uwsgi.wsgi_req);
// push wsgi_request in the unused stack
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
}
else if (uwsgi.wsgi_req->waiting_fds || uwsgi.wsgi_req->async_timeout) {
// remove this request from suspended list
runqueue_remove(current_request);
}
current_request = next_async_request;
}
}
return NULL;
}
#endif
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = null
+33
View File
@@ -0,0 +1,33 @@
[uwsgi]
xml = true
ini = true
yaml = true
snmp = true
sctp = false
spooler = true
embedded = true
udp = true
multicast = true
threading = true
sendfile = true
minterpreters = true
async = true
evdis = false
ldap = auto
pcre = auto
debug = false
unbit = false
xml_implementation = libxml2
plugins =
bin_name = uwsgi
plugin_dir = .
embedded_plugins = python, ping, nagios, rpc, fastrouter, http, ugreen
locking = auto
event = auto
timer = auto
filemonitor = auto
[python]
paste = true
web3 = true
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = +,erlang
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = lua
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
plugins = lua
+33
View File
@@ -0,0 +1,33 @@
[uwsgi]
xml = true
ini = true
snmp = true
sctp = false
erlang = false
spooler = false
embedded = false
udp = true
multicast = false
threading = true
sendfile = true
nagios = true
proxy = true
minterpreters = true
async = true
ugreen = false
http = true
evdis = false
ldap = true
routing = false
stackless = false
debug = false
unbit = false
xml_implementation = libxml2
plugins = python, ping, rack
bin_name = uwsgi
plugin_dir = .
embedded_plugins =
[python]
paste = true
web3 = true
+4
View File
@@ -0,0 +1,4 @@
[uwsgi]
inherit = default
plugin_dir = /usr/lib/uwsgi
embedded_plugins = null
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = psgi
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = +,erlang,pyerl
+7
View File
@@ -0,0 +1,7 @@
[uwsgi]
inherit = default
embedded_plugins = +,lua
[python]
paste = true
web3 = true
+31
View File
@@ -0,0 +1,31 @@
[uwsgi]
xml = true
ini = true
snmp = true
sctp = false
erlang = false
spooler = true
embedded = true
udp = true
multicast = true
threading = true
sendfile = true
proxy = true
minterpreters = true
async = true
http = true
evdis = false
ldap = false
routing = false
stackless = false
debug = false
unbit = false
xml_implementation = libxml2
plugins =
bin_name = uwsgi
plugin_dir = .
embedded_plugins = python, ping, nagios, rack
[python]
paste = true
web3 = true
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
inherit = default
embedded_plugins = rack, ping, nagios, rpc
+30
View File
@@ -0,0 +1,30 @@
[uwsgi]
xml = true
ini = true
yaml = true
snmp = true
sctp = false
erlang = false
spooler = false
embedded = false
udp = true
multicast = false
threading = true
sendfile = true
nagios = true
proxy = true
minterpreters = true
async = true
ugreen = false
http = true
evdis = false
ldap = false
routing = false
stackless = false
debug = false
unbit = false
xml_implementation = libxml2
plugins = rack
bin_name = uwsgi
plugin_dir = .
embedded_plugins =
+23
View File
@@ -0,0 +1,23 @@
[uwsgi]
xml = true
ini = true
yaml = true
snmp = false
sctp = false
spooler = true
embedded = true
udp = true
multicast = false
threading = true
sendfile = true
nagios = false
minterpreters = true
async = true
ldap = true
debug = false
unbit = true
xml_implementation = libxml2
plugins =
bin_name = /opt/unbit/bin/uwsgi
plugin_dir = /opt/unbit/uwsgi_plugins
embedded_plugins =
+5
View File
@@ -0,0 +1,5 @@
[uwsgi]
inherit = unbit
embedded_plugins = python
bin_name = ../bin/uwsgi
plugin_dir = ../bin/uwsgi_plugins
+588
View File
@@ -0,0 +1,588 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
struct uwsgi_subscriber_name *uwsgi_get_subscriber(struct uwsgi_dict *udict, char *key, uint16_t keylen) {
uint64_t ovl;
struct uwsgi_subscriber *usub;
struct uwsgi_subscriber_name *ret = NULL;
usub = (struct uwsgi_subscriber *) uwsgi_dict_get(udict, key, keylen, &ovl);
if (usub == NULL || !ovl) return NULL;
if (!usub->nodes) return NULL;
if (usub && ovl) {
ret = &usub->names[usub->current];
// dead node
if (ret->len == 0) {
if (usub->current == usub->nodes-1) {
usub->nodes--;
}
// retry with another node (if available)
if (usub->nodes > 0) {
usub->current++;
if (usub->current >= usub->nodes) usub->current = 0;
return uwsgi_get_subscriber(udict, key, keylen);
}
}
if (usub->nodes > 1) {
usub->current++;
if (usub->current >= usub->nodes) usub->current = 0;
}
}
return ret;
}
void uwsgi_add_subscriber(struct uwsgi_dict *udict, char *key, uint16_t keylen, char *address, uint64_t address_len) {
char *ptr;
uint64_t vallen = 0;
struct uwsgi_subscriber *usub, nusub;
int found = 0;
int i;
ptr = uwsgi_dict_get(udict, key, keylen, &vallen);
if (ptr && vallen) {
usub = (struct uwsgi_subscriber *) ptr;
for(i=0;i<(int)usub->nodes;i++) {
if (!uwsgi_strncmp(usub->names[i].name, usub->names[i].len, address, address_len)) {
found = 1;
break;
}
}
if (!found) {
found = usub->nodes;
// check for unallocated slot
for(i=0;i<(int)usub->nodes;i++) {
if (usub->names[i].len == 0) {
found = i;
break;
}
}
usub->names[found].len = address_len;
memcpy(usub->names[found].name, address, address_len);
if (found == (int) usub->nodes) {
usub->nodes++;
}
}
return;
}
else {
nusub.nodes = 1;
nusub.current = 0;
memcpy(nusub.names[0].name, address, address_len);
uwsgi_dict_set(udict, key, keylen, (char *) &nusub, sizeof(struct uwsgi_subscriber));
}
}
struct uwsgi_dict *uwsgi_dict_create(uint64_t items, uint64_t blocksize) {
int i;
struct uwsgi_dict *udict = (struct uwsgi_dict *) mmap(NULL, sizeof(uint64_t) * UMAX16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!udict) {
uwsgi_error("mmap()");
exit(1);
}
if (!blocksize) blocksize = 4096;
if (blocksize % uwsgi.page_size != 0) {
uwsgi_log("invalid shared dictionary blocksize %llu: must be a multiple of memory page size (%d bytes)\n", (unsigned long long) udict->blocksize, uwsgi.page_size);
exit(1);
}
udict->blocksize = blocksize;
udict->max_items = items;
udict->hashtable = (uint64_t *) mmap(NULL, sizeof(uint64_t) * UMAX16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!udict->hashtable) {
uwsgi_error("mmap()");
exit(1);
}
memset(udict->hashtable, 0, sizeof(uint64_t) * UMAX16);
udict->unused_stack = (uint64_t *) mmap(NULL, sizeof(uint64_t) * udict->max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!udict->unused_stack) {
uwsgi_error("mmap()");
exit(1);
}
memset(udict->unused_stack, 0, sizeof(uint64_t) * udict->max_items);
udict->items = (struct uwsgi_dict_item *) mmap(NULL, sizeof(struct uwsgi_dict_item) * udict->max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!udict->items) {
uwsgi_error("mmap()");
exit(1);
}
udict->data = mmap(NULL, udict->blocksize * udict->max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!udict->data) {
uwsgi_error("mmap()");
exit(1);
}
for(i=0;i< (int) udict->max_items;i++) {
memset(&udict->items[i], 0, sizeof(struct uwsgi_dict_item));
}
udict->first_available_item = 1;
udict->unused_stack_ptr = 0;
udict->lock = uwsgi_mmap_shared_lock();
uwsgi_lock_init(udict->lock);
return udict;
}
uint32_t djb33x_hash(char *key, int keylen) {
register uint32_t hash = 5381;
int i;
for(i=0;i<keylen;i++) {
hash = ((hash << 5) + hash) ^ key[i];
}
return hash;
}
inline uint64_t uwsgi_dict_get_index(struct uwsgi_dict *udict, char *key, uint16_t keylen) {
uint32_t hash = djb33x_hash(key, keylen);
int hash_key = hash % 0xffff;
uint64_t slot = udict->hashtable[hash_key];
struct uwsgi_dict_item *udi;
udi = &udict->items[slot];
// first round
if (udi->djbhash != hash) goto cycle;
if (udi->keysize != keylen) goto cycle;
if (memcmp(udi->key, key, keylen)) goto cycle;
return slot;
cycle:
while(udi->next) {
slot = udi->next;
udi = &udict->items[slot];
if (udi->djbhash != hash) continue;
if (udi->keysize != keylen) continue;
if (!memcmp(udi->key, key, keylen)) return slot;
}
return 0;
}
char *uwsgi_dict_get(struct uwsgi_dict *udict, char *key, uint16_t keylen, uint64_t *valsize) {
uint64_t index = uwsgi_dict_get_index(udict, key, keylen);
if (index) {
*valsize = udict->items[index].valsize;
udict->items[index].hits++;
return udict->data+(index*udict->blocksize);
}
return NULL;
}
int uwsgi_dict_del(struct uwsgi_dict *udict, char *key, uint16_t keylen) {
uint64_t index = 0;
struct uwsgi_dict_item *udi;
int ret = -1;
index = uwsgi_dict_get_index(udict, key, keylen);
if (index) {
udi = &udict->items[index] ;
udi->keysize = 0;
udi->valsize = 0;
udict->unused_stack_ptr++;
udict->unused_stack[udict->unused_stack_ptr] = index;
// try to return to initial condition...
if (index == udict->first_available_item-1) {
udict->first_available_item--;
}
ret = 0;
// relink collisioned entry
if (udi->prev) {
udict->items[udi->prev].next = udi->next;
}
if (udi->next) {
udict->items[udi->next].prev = udi->prev;
}
if (!udi->prev && !udi->next) {
// reset hashtable entry
udict->hashtable[udi->djbhash % 0xffff] = 0;
}
udi->djbhash = 0;
udi->prev = 0;
udi->next = 0;
}
return ret;
}
inline uint64_t uwsgi_cache_get_index(char *key, uint16_t keylen) {
uint32_t hash = djb33x_hash(key, keylen);
int hash_key = hash % 0xffff;
uint64_t slot = uwsgi.cache_hashtable[hash_key];
struct uwsgi_cache_item *uci;
//uwsgi_log("found slot %d for key %d\n", slot, hash_key);
uci = &uwsgi.cache_items[slot];
// first round
if (uci->djbhash != hash) goto cycle;
if (uci->keysize != keylen) goto cycle;
if (memcmp(uci->key, key, keylen)) goto cycle;
return slot;
cycle:
while(uci->next) {
slot = uci->next;
uci = &uwsgi.cache_items[slot];
if (uci->djbhash != hash) continue;
if (uci->keysize != keylen) continue;
if (!memcmp(uci->key, key, keylen)) return slot;
}
return 0;
}
uint32_t uwsgi_cache_exists(char *key, uint16_t keylen) {
return uwsgi_cache_get_index(key, keylen);
}
char *uwsgi_cache_get(char *key, uint16_t keylen, uint64_t *valsize) {
uint64_t index = uwsgi_cache_get_index(key, keylen);
if (index) {
if (uwsgi.cache_items[index].flags & UWSGI_CACHE_FLAG_UNGETTABLE) return NULL;
*valsize = uwsgi.cache_items[index].valsize;
uwsgi.cache_items[index].hits++;
return uwsgi.cache+(index*uwsgi.cache_blocksize);
}
return NULL;
}
int uwsgi_cache_del(char *key, uint16_t keylen) {
uint64_t index = 0;
struct uwsgi_cache_item *uci;
int ret = -1;
index = uwsgi_cache_get_index(key, keylen);
if (index) {
uci = &uwsgi.cache_items[index] ;
uci->keysize = 0;
uci->valsize = 0;
uwsgi.shared->cache_unused_stack_ptr++;
uwsgi.cache_unused_stack[uwsgi.shared->cache_unused_stack_ptr] = index;
// try to return to initial condition...
if (index == uwsgi.shared->cache_first_available_item-1) {
uwsgi.shared->cache_first_available_item--;
//uwsgi_log("FACI: %llu STACK PTR: %llu\n", (unsigned long long) uwsgi.shared->cache_first_available_item, (unsigned long long) uwsgi.shared->cache_unused_stack_ptr);
}
ret = 0;
// relink collisioned entry
if (uci->prev) {
uwsgi.cache_items[uci->prev].next = uci->next;
}
if (uci->next) {
uwsgi.cache_items[uci->next].prev = uci->prev;
}
if (!uci->prev && !uci->next) {
// reset hashtable entry
//uwsgi_log("!!! resetted hashtable entry !!!\n");
uwsgi.cache_hashtable[uci->djbhash % 0xffff] = 0;
}
uci->djbhash = 0;
uci->prev = 0;
uci->next = 0;
}
return ret;
}
void uwsgi_cache_fix() {
uint64_t i;
for(i=0;i< uwsgi.cache_max_items;i++) {
// valid record ?
if (uwsgi.cache_items[i].keysize) {
if (!uwsgi.cache_items[i].prev) {
// put value in hash_table
uwsgi.cache_hashtable[ uwsgi.cache_items[i].djbhash % 0xffff] = i;
}
}
else {
// put this record in unused stack
uwsgi.shared->cache_first_available_item = i;
uwsgi.shared->cache_unused_stack_ptr++;
uwsgi.cache_unused_stack[uwsgi.shared->cache_unused_stack_ptr] = i;
}
}
}
int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint64_t expires, uint16_t flags) {
uint64_t index = 0, last_index = 0 ;
struct uwsgi_cache_item *uci, *ucii;
int ret = -1;
int slot;
if (!keylen || !vallen) return -1;
if (keylen > UWSGI_CACHE_MAX_KEY_SIZE) return -1;
if (uwsgi.shared->cache_first_available_item >= uwsgi.cache_max_items && !uwsgi.shared->cache_unused_stack_ptr) {
uwsgi_log("*** DANGER cache is FULL !!! ***\n");
goto end;
}
//uwsgi_log("putting cache data in key %.*s %d\n", keylen, key, vallen);
index = uwsgi_cache_get_index(key, keylen);
if (!index) {
if (uwsgi.shared->cache_unused_stack_ptr) {
//uwsgi_log("!!! REUSING CACHE SLOT !!! (faci: %llu)\n", (unsigned long long) uwsgi.shared->cache_first_available_item);
index = uwsgi.cache_unused_stack[uwsgi.shared->cache_unused_stack_ptr];
uwsgi.shared->cache_unused_stack_ptr--;
}
else {
index = uwsgi.shared->cache_first_available_item;
if (uwsgi.shared->cache_first_available_item < uwsgi.cache_max_items) {
uwsgi.shared->cache_first_available_item++;
}
}
uci = &uwsgi.cache_items[index] ;
if (expires) expires += time(NULL);
uci->expires = expires;
uci->djbhash = djb33x_hash(key, keylen);
uci->hits = 0;
uci->flags = flags;
memcpy(uci->key, key, keylen);
memcpy(uwsgi.cache+(index*uwsgi.cache_blocksize), val, vallen);
// set this as late as possibile (to reduce races risk)
uci->valsize = vallen;
uci->keysize = keylen;
ret = 0;
// now put the value in the 16bit hashtable
slot = uci->djbhash % 0xffff;
if (uwsgi.cache_hashtable[slot] == 0) {
uwsgi.cache_hashtable[slot] = index;
}
else {
//uwsgi_log("HASH COLLISION !!!!\n");
// append to first available next
last_index = uwsgi.cache_hashtable[slot];
ucii = &uwsgi.cache_items[ last_index ];
while(ucii->next) {
last_index = ucii->next;
ucii = &uwsgi.cache_items[ last_index ];
}
ucii->next = index;
uci->prev = last_index;
}
}
end:
return ret;
}
int uwsgi_dict_set(struct uwsgi_dict *udict, char *key, uint16_t keylen, char *val, uint64_t vallen) {
uint64_t index = 0, last_index = 0 ;
struct uwsgi_dict_item *udi, *udii;
int ret = -1;
int slot;
if (!keylen || !vallen) return -1;
if (keylen > UWSGI_CACHE_MAX_KEY_SIZE) return -1;
if (udict->first_available_item >= udict->max_items && !udict->unused_stack_ptr) {
uwsgi_log("*** DANGER dictionary %p is FULL !!! ***\n", udict);
goto end;
}
index = uwsgi_dict_get_index(udict, key, keylen);
if (!index) {
if (udict->unused_stack_ptr) {
index = udict->unused_stack[udict->unused_stack_ptr];
udict->unused_stack_ptr--;
}
else {
index = udict->first_available_item;
if (udict->first_available_item < udict->max_items) {
udict->first_available_item++;
}
}
udi = &udict->items[index] ;
udi->djbhash = djb33x_hash(key, keylen);
udi->hits = 0;
memcpy(udi->key, key, keylen);
memcpy(udict->data+(index*udict->blocksize), val, vallen);
// set this as late as possibile (to reduce races risk)
udi->valsize = vallen;
udi->keysize = keylen;
ret = 0;
// now put the value in the 16bit hashtable
slot = udi->djbhash % 0xffff;
if (udict->hashtable[slot] == 0) {
udict->hashtable[slot] = index;
}
else {
// append to first available next
last_index = udict->hashtable[slot];
udii = &udict->items[ last_index ];
while(udii->next) {
last_index = udii->next;
udii = &udict->items[ last_index ];
}
udii->next = index;
udi->prev = last_index;
}
}
end:
return ret;
}
void cache_command(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
struct wsgi_request *wsgi_req = (struct wsgi_request *) data;
uint64_t tmp_vallen = 0;
if (vallen > 0) {
if (!uwsgi_strncmp(key, keylen, "key", 3)) {
val = uwsgi_cache_get(val, vallen, &tmp_vallen);
if (val && tmp_vallen > 0) {
wsgi_req->response_size = write(wsgi_req->poll.fd, val, tmp_vallen);
}
}
else if (!uwsgi_strncmp(key, keylen, "get", 3)) {
val = uwsgi_cache_get(val, vallen, &tmp_vallen);
if (val && vallen > 0) {
wsgi_req->response_size = write(wsgi_req->poll.fd, val, tmp_vallen);
}
else {
wsgi_req->response_size = write(wsgi_req->poll.fd, "HTTP/1.0 404 Not Found\r\n\r\n<h1>Not Found</h1>", 44);
}
}
}
}
int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
uint64_t vallen = 0;
char *value;
char *argv[3];
uint8_t argc = 0;
switch(wsgi_req->uh.modifier2) {
case 0:
// get
if (wsgi_req->uh.pktsize > 0) {
value = uwsgi_cache_get(wsgi_req->buffer, wsgi_req->uh.pktsize, &vallen);
if (value && vallen > 0) {
wsgi_req->uh.pktsize = vallen;
wsgi_req->response_size = write(wsgi_req->poll.fd, &wsgi_req->uh, 4);
wsgi_req->response_size += write(wsgi_req->poll.fd, value, vallen);
}
}
break;
case 1:
// set
if (wsgi_req->uh.pktsize > 0) {
argc = 3;
if (!uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh.pktsize, argv, &argc)) {
if (argc > 1) {
uwsgi_cache_set(argv[0], strlen(argv[0]), argv[1], strlen(argv[1]), 0, 0);
}
}
}
break;
case 2:
// del
if (wsgi_req->uh.pktsize > 0) {
uwsgi_cache_del(wsgi_req->buffer, wsgi_req->uh.pktsize);
}
break;
case 3:
case 4:
// dict
if (wsgi_req->uh.pktsize > 0) {
uwsgi_hooked_parse(wsgi_req->buffer, wsgi_req->uh.pktsize, cache_command, (void *) wsgi_req);
}
break;
case 5:
// get (uwsgi + stream)
if (wsgi_req->uh.pktsize > 0) {
value = uwsgi_cache_get(wsgi_req->buffer, wsgi_req->uh.pktsize, &vallen);
if (value && vallen > 0) {
wsgi_req->uh.pktsize = 0;
wsgi_req->uh.modifier2 = 1;
wsgi_req->response_size = write(wsgi_req->poll.fd, &wsgi_req->uh, 4);
wsgi_req->response_size += write(wsgi_req->poll.fd, value, vallen);
}
else {
wsgi_req->uh.pktsize = 0;
wsgi_req->uh.modifier2 = 0;
wsgi_req->response_size = write(wsgi_req->poll.fd, &wsgi_req->uh, 4);
}
}
break;
}
return 0;
}
struct uwsgi_plugin uwsgi_cache_plugin = {
.name = "cache",
.modifier1 = 111,
.request = uwsgi_cache_request,
};
+18
View File
@@ -0,0 +1,18 @@
require 'fiber'
require 'sinatra'
get '/hi' do
class Response
def each
for i in 1..10
yield "ciao<br/>"
Fiber.yield
end
end
end
Response.new
end
run Sinatra::Application
+7
View File
@@ -0,0 +1,7 @@
require 'sinatra'
get '/hi' do
"Hello World"
end
run Sinatra::Application
+68 -68
View File
@@ -17,10 +17,10 @@ sub new {
sub run {
my ($self, $app) = @_;
my $server ;
my $server;
if (exists($ENV{'UWSGI_FD'})) {
$server = IO::Socket::UNIX->new_from_fd($ENV{'UWSGI_FD'}, '+<');
$server = IO::Socket::UNIX->new_from_fd($ENV{'UWSGI_FD'}, '+<');
}
else {
$server = IO::Socket::INET->new(LocalPort => $self->{port}, LocalAddr => $self->{host}, Listen => 100, ReuseAddr => 1);
@@ -28,62 +28,62 @@ sub run {
while ( my $client = $server->accept ) {
my $head = '';
my $remains = 4 ;
my $head = '';
my $remains = 4;
while($remains) {
$client->recv(my $buf, $remains);
last unless $buf;
$head.=$buf;
$remains -= length($buf);
}
while($remains) {
$client->recv(my $buf, $remains);
last unless $buf;
$head.=$buf;
$remains -= length($buf);
}
if (length($head) != 4) {
$client->close ;
next;
}
if (length($head) != 4) {
$client->close;
next;
}
my ($mod1, $envsize, $mod2) = unpack('CvC', $head) ;
my ($mod1, $envsize, $mod2) = unpack('CvC', $head);
unless ($envsize) {
$client->close ;
next;
}
unless ($envsize) {
$client->close;
next;
}
$remains = $envsize ;
my $envbuf = '' ;
while($remains) {
my $buf ;
if ($remains >= 4096) {
$client->recv($buf, 4096);
}
else {
$client->recv($buf, $remains);
}
$remains = $envsize;
my $envbuf = '';
while($remains) {
my $buf;
if ($remains >= 4096) {
$client->recv($buf, 4096);
}
else {
$client->recv($buf, $remains);
}
unless($buf) {
$client->close ;
next;
}
unless($buf) {
$client->close;
next;
}
$envbuf.=$buf;
$remains -= length($buf);
}
$envbuf.=$buf;
$remains -= length($buf);
}
if (length($envbuf) != $envsize ) {
$client->close ;
next;
}
if (length($envbuf) != $envsize ) {
$client->close;
next;
}
my %env ;
my %env;
my $i = 0;
while($i < $envsize) {
my $kl = unpack('v', substr($envbuf, $i, 2)) ; $i+=2;
my $key = substr($envbuf, $i, $kl); $i+=$kl;
my $vl = unpack('v', substr($envbuf, $i, 2)) ; $i+=2;
$env{$key} = substr($envbuf, $i, $vl); $i+=$vl;
}
my $i = 0;
while($i < $envsize) {
my $kl = unpack('v', substr($envbuf, $i, 2)); $i+=2;
my $key = substr($envbuf, $i, $kl); $i+=$kl;
my $vl = unpack('v', substr($envbuf, $i, 2)); $i+=2;
$env{$key} = substr($envbuf, $i, $vl); $i+=$vl;
}
my $env = {
%env,
@@ -105,40 +105,40 @@ sub run {
}
elsif (ref $res eq 'CODE') {
$res->(sub {
$self->_handle_response($client, $env{'SERVER_PROTOCOL'}, $_[0]);
});
$self->_handle_response($client, $env{'SERVER_PROTOCOL'}, $_[0]);
});
}
else {
die "Bad response $res";
}
$client->close ;
$client->close;
}
}
sub _handle_response {
my ($self, $client, $protocol, $res) = @_;
my ($self, $client, $protocol, $res) = @_;
$client->send($protocol.' '.$res->[0].' '.HTTP::Status::status_message( $res->[0] )."\r\n");
$client->send($protocol.' '.$res->[0].' '.HTTP::Status::status_message( $res->[0] )."\r\n");
my $headers = $res->[1];
my $hdrs = '';
while (my ($k, $v) = splice @$headers, 0, 2) {
$hdrs .= "$k: $v\r\n";
}
$hdrs .= "\r\n";
my $headers = $res->[1];
my $hdrs = '';
while (my ($k, $v) = splice @$headers, 0, 2) {
$hdrs .= "$k: $v\r\n";
}
$hdrs .= "\r\n";
$client->send($hdrs);
$client->send($hdrs);
my $cb = sub { $client->send($_[0]) };
my $body = $res->[2];
if (defined $body) {
Plack::Util::foreach($body, $cb);
}
else {
return Plack::Util::inline_object write => $cb,close => sub { };
}
my $cb = sub { $client->send($_[0]) };
my $body = $res->[2];
if (defined $body) {
Plack::Util::foreach($body, $cb);
}
else {
return Plack::Util::inline_object write => $cb,close => sub { };
}
}
1;
+66
View File
@@ -0,0 +1,66 @@
import django
from django.core.management.base import BaseCommand
from django.conf import settings
import os
import sys
class Command(BaseCommand):
help = "Runs this project as a uWSGI application. Requires the uwsgi binary in system path."
http_port = '8000'
socket_addr = None
def handle(self, *args, **options):
for arg in args:
k,v = arg.split('=')
if k == 'http':
if self.http_port:
self.http_port = v
elif k == 'socket':
self.http_port = None
self.socket_addr = v
# load http and python plugin: first the specific version, otherwise try with the generic one
if self.http_port:
os.environ['UWSGI_PLUGINS'] = 'http,python%d%d:python' % (sys.version_info[0], sys.version_info[1])
else:
os.environ['UWSGI_PLUGINS'] = 'python%d%d:python' % (sys.version_info[0], sys.version_info[1])
# load the Django WSGI handler
os.environ['UWSGI_MODULE'] = 'django.core.handlers.wsgi:WSGIHandler()'
# DJANGO settings
if options['settings']:
os.environ['DJANGO_SETTINGS_MODULE'] = options['settings']
else:
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
# bind the http server to the default port
if self.http_port:
os.environ['UWSGI_HTTP'] = ':%s' % self.http_port
elif self.socket_addr:
os.environ['UWSGI_SOCKET'] = self.socket_addr
# map admin static files
os.environ['UWSGI_STATIC_MAP'] = '%s=%s' % (settings.ADMIN_MEDIA_PREFIX, os.path.join(django.__path__[0], 'contrib', 'admin', 'media'))
# remove sockets/pidfile at exit
os.environ['UWSGI_VACUUM'] = '1'
# retrieve/set the PythonHome
os.environ['UWSGI_PYHOME'] = sys.prefix
# increase buffer size a bit
os.environ['UWSGI_BUFFER_SIZE'] = '8192'
# add threads for concurrency
os.environ['UWSGI_THREADS'] = '8'
# enable the master process
os.environ['UWSGI_MASTER'] = '1'
# use uWSGI python module aliasing to fix the PYTHONPATH
os.environ['UWSGI_PYMODULE_ALIAS'] = '%s=./' % os.path.basename(os.getcwd())
# exec the uwsgi binary
os.execvp('uwsgi', ('uwsgi',))
def usage(self, subcomand):
return r"""
run this project on the uWSGI server
http=PORT run the embedded http server on port PORT
socket=ADDR bind the uwsgi server on address ADDR (this will disable the http server)
"""
+15
View File
@@ -0,0 +1,15 @@
# uWSGI - manage uWSGI application server
#
description "uWSGI"
start on runlevel [2345]
stop on runlevel [!2345]
respawn
env LOGTO=/tmp/uwsgi.log
env BINPATH=/home/foo/uwsgi/uwsgi
# --no-orphans avoid workers without master
exec $BINPATH --no-orphans --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -m simple_app --logto $LOGTO -M -p 4
+301 -274
View File
@@ -1,303 +1,330 @@
# Copyright 2009 Unbit S.a.s. <info@unbit.it>
# see the COPYRIGHT file
require 'rubygems'
require 'socket'
require 'rack'
require 'rack/content_length'
require 'rack/rewindable_input'
require 'stringio'
$stdout.sync = true
options = {}
require 'optparse'
options = {
:processes => 1,
:threads => 1,
:master => false,
:logging => true,
:static => true,
:config => nil,
:cachehack => false
}
opts = OptionParser.new do |opts|
opts.on("-p", "--processes=nproc", Integer, '') { |p| options[:processes] = p }
opts.on("-t", "--threads=nthreads", Integer, '') { |t| options[:threads] = t }
opts.on("-M", "--master", '') { options[:master] = true }
opts.on("-L", "--no-logging", '') { options[:logging] = false }
opts.on("-S", "--no-static", '') { options[:static] = false }
opts.on("-C", "--cache-hack", '') { options[:cachehack] = true }
opts.parse! ARGV
end
if ARGV[0]
options[:config] = ARGV[0]
end
def human_round(float)
(float * (10 ** 2)).round / (10 ** 2).to_f
end
$domain = ARGV.last.gsub('[','').gsub(']','')
$unbit_log_base = "[uRack/Unbit on #{$domain}]"
$limit_as = human_round(Process.getrlimit(Process::RLIMIT_AS)[1].to_f/1024/1024)
puts "#{$unbit_log_base} process address space limit is #{$limit_as} MB"
$uidsec_size = syscall(357,0,0)
puts "#{$unbit_log_base} need #{$uidsec_size} bytes to store uidsec_struct..."
$uidsec = '1' * $uidsec_size
puts "#{$unbit_log_base} uidsec_struct allocated."
options[:processes] = 1
options[:serve_file] = nil
options[:max_input_size] = 8
options[:unbit_debug] = false
options[:master] = true
options[:gc_freq] = nil
puts "[#{Time.new}] uRack: loading app [#{RAILS_ROOT}]..."
starttime = Time.now
require "config/environment"
require 'socket'
require 'rubygems'
require 'rack'
require 'rack/utils'
require 'rack/content_length'
$requests = 0
$workers = Array.new
$mywid = 0
module Rack
module Handler
class Unbit
class Tempfile < ::Tempfile
def _close
@tmpfile.close if @tmpfile
@data[1] = nil if @data
@tmpfile = nil
end
end
def self.run(app, options={})
master_pid = Process.pid
options[:processes] ||= 1
class RailsCachingHack
def initialize app
@app = app
end
server = UNIXServer.for_fd(0)
def stripuri(uri)
uri = uri.split('/')
uri.slice!(1)
val = uri.join('/')
end
def call env
env['PATH_INFO'] = stripuri(env['PATH_INFO']) if env['PATH_INFO']
env['REQUEST_URI'] = stripuri(env['REQUEST_URI']) if env['REQUEST_URI']
env['REQUEST_URI'] = '/' if env['REQUEST_URI'] == ''
@app.call env
end
end
$workers = Array.new
module Handler
class Unbit
if options[:master]
$0 = "uRack #{ARGV.last}"
pid = Process.fork
if pid.to_i > 0
puts "[#{Time.new}] uRack: spawned rack worker 1 (pid: #{pid})"
$workers[1] = pid ;
end
end
def self.run(app, options={})
server = UNIXServer.for_fd(0)
# the check on master pid is necessary
# without it the first worker will execute this part
if options[:processes] > 1 and Process.pid == master_pid
for p in 2..options[:processes]
pid = Process.fork
break if pid.to_i == 0
puts "[#{Time.new}] uRack: spawned rack worker #{p} (pid: #{pid})"
$workers[p] = pid ;
end
end
can_spawn = true
if options[:master]
$0 = 'uRack master'
$workers[0] = Process.pid
ulog("master process enabled (pid: #{$workers[0]})")
$workers[1] = Process.fork
if $workers[1].to_i > 0
ulog("spawned worker 1 (pid: #{$workers[1]})")
elsif $workers[1].to_i == 0
$0 = "uRack worker 1"
$mywid = 1
can_spawn = false
end
else
$0 = 'uRack worker 1'
$workers[0] = nil
$workers[1] = Process.pid
$mywid = 1
ulog("spawned worker 1 (pid: #{$workers[1]})")
end
# am i the master ?
if options[:master] and Process.pid == master_pid
Signal.trap('TERM') do
puts "[#{Time.new}] uRack: gracefully killing uRack"
for wid in 1..options[:processes]
Process.kill('TERM', $workers[wid]);
end
exit 0;
end
Signal.trap('QUIT') do
puts "[#{Time.new}] uRack: brutally killing uRack"
for wid in 1..options[:processes]
Process.kill('INT', $workers[wid]);
end
exit 0;
end
puts "[#{Time.new}] uRack: the master process manager is alive."
while 1
pid = Process.waitpid
puts "[#{Time.new}] uRack: worker died ! (pid: #{pid})"
newpid = Process.fork
break if newpid.to_i == 0
puts "[#{Time.new}] uRack: respawned rack worker (pid: #{newpid})"
for wid in 1..options[:processes]
if $workers[wid] == pid
$workers[wid] = newpid
break
end
end
end
end
if Process.pid != master_pid
$0 = $0.gsub(/^uRack/,'urack')
Signal.trap("TERM") do
puts "[#{Time.new}] uRack: grecefully killing process #{Process.pid}..."
if $in_request == 0
puts "[#{Time.new}] uRack: goodbye to process #{Process.pid}"
exit 0
end
$manage_next_request = nil
end
Signal.trap('INT') do
puts "[#{Time.new}] uRack: brutally killing process #{Process.pid}..."
exit 0
end
Signal.trap('PIPE') do
puts "[#{Time.new}] uRack: the webserver (or the client) has closed the connection with process #{Process.pid} !!!"
end
end
max_input_size = options[:max_input_size].to_i * 1024
requests = 0
null_post = StringIO.new('')
options[:app_name] ||= Dir.getwd
app = Rack::ContentLength.new(app)
$manage_next_request = true
if options[:gc_freq].to_i > 1
GC.disable
end
while $manage_next_request
$in_request = 0
client = server.accept
$in_request = 1
timed_out = false
ver, size, arg1 = client.recvfrom(4)[0].unpack('CvC')
vars = client.recvfrom(size)[0]
env = Hash.new
i = 0
while i < size
kl = vars[i, 2].unpack('v')[0]
i = i + 2
key = vars[i, kl]
i = i + kl
vl = vars[i, 2].unpack('v')[0]
i = i + 2
value = vars[i, vl]
i = i + vl
env[key] = value
end
rack_input = null_post
env.delete 'CONTENT_LENGTH' if env['CONTENT_LENGTH'] == ''
if env['CONTENT_LENGTH'].to_i > 0
cl = env['CONTENT_LENGTH'].to_i
if cl <= max_input_size
poststr = ''
while poststr.size < cl
poststr = poststr + client.recvfrom(cl-poststr.size)[0] ;
end
rack_input = StringIO.new(poststr)
else
rack_input = Tempfile.new('UnbitRack')
rack_input.chmod(0000)
bytes_read = 0
while bytes_read < cl
buf = client.recvfrom(4096)[0]
rack_input.write(buf)
bytes_read += buf.size
end
rack_input.rewind
end
end
env["SCRIPT_NAME"] = ""
env.update({"rack.version" => [0,1],
"rack.input" => rack_input,
"rack.errors" => $stderr,
"rack.multithread" => false,
"rack.multiprocess" => true,
"rack.run_once" => false,
"rack.url_scheme" => "http"
})
env["QUERY_STRING"] ||= ""
env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
env["REQUEST_PATH"] ||= "/"
begin
#puts env.inspect
$start_of_request = Time.new
status, headers, body = app.call(env)
$speed = Time.new - $start_of_request
client.print "#{env["HTTP_VERSION"]} #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]}\r\n"
headers.each {|k,vs|
vs.split("\n").each { |v|
client.print "#{k}: #{v}\r\n"
}
}
client.print "\r\n"
client.flush
body.each {|part|
client.print part
client.flush
}
rescue Errno::EPIPE
puts "[#{Time.new}] uRack: the webserver (or the client) has closed the connection with process #{Process.pid} !!!"
timed_out = true
ensure
if rack_input.respond_to? :unlink
rack_input.unlink
end
unless rack_input.closed?
rack_input.close
end
client.close
requests = requests+1
# logging
$stderr.puts "[#{Time.new}] uRack: [#{options[:app_name]}] req: #{requests} ip: #{env['REMOTE_ADDR']} pid: #{Process.pid} as: #{human_round(syscall(356).to_f/1024/1024)} MB => #{env['REQUEST_METHOD']} #{env['REQUEST_URI']} in #{$speed} secs [#{status}]#{' TIMED OUT !!!' if timed_out}"
if syscall(357, $uidsec, 0) == $uidsec_size
if $uidsec[120..123].unpack('i')[0] > 0
$stderr.puts "[#{Time.new}] uRack: found a memory allocation error for request #{requests} (pid: #{Process.pid}). Better to kill myself..."
$manage_next_request = nil
end
end
$uidsec = '1' * $uidsec_size
if options[:unbit_debug]
current_as = human_round( (syscall(356).to_f/1024/1024) - $last_as )
$stderr.puts "#{$unbit_log_base} resource status after request #{requests}: AS for this request: #{current_as} MB | OBJ for this request: #{ObjectSpace.each_object {} - $last_obj} | OBJ total: #{ObjectSpace.each_object {}}"
$last_as = human_round(syscall(356).to_f/1024/1024) ;
$last_obj = ObjectSpace.each_object {}
end
if options[:gc_freq].to_i > 1
if requests % options[:gc_freq].to_i == 0
$stderr.puts "[#{Time.new}] uRack: [#{options[:app_name]}] calling GC for pid #{Process.pid} after #{requests} requests."
GC.enable ; GC.start ; GC.disable
end
end
end
end
puts "[#{Time.new}] uRack: goodbye to process #{Process.pid}"
if options[:processes] > 1 and can_spawn
for p in 2..options[:processes]
$workers[p] = Process.fork
if $workers[p].to_i == 0
$0 = "uRack worker #{p}"
$mywid = p
break
elsif $workers[p].to_i > 0
ulog("spawned worker #{p} (pid: #{$workers[p]})")
end
end
end
# am i the master ?
if options[:master] and Process.pid == $workers[0]
while 1
i_am_a_child = false
pid = Process.waitpid
for wid in 1..options[:processes]
if $workers[wid] == pid
ulog("worker #{wid} died ! (pid: #{pid})")
$workers[wid] = Process.fork
if $workers[wid].to_i == 0
$0 = "uRack worker #{wid}"
i_am_a_child = true
$mywid = wid
break
elsif $workers[wid].to_i > 0
ulog("respawned worker #{wid} (pid: #{$workers[wid]})")
end
end
end
break if i_am_a_child
end
end
if options[:threads] > 2
for t in 2..options[:threads]
wt = Thread.new do
ulog("spawning thread #{t} on worker #{$mywid}")
while client = server.accept
serve client, app, options
end
end
end
end
while client = server.accept
serve client, app, options
end
end
def self.serve(client, app, options)
speed = Time.now
head, sender = client.recvfrom(4)
unless head
client.close
return
end
mod1, size, mod2 = head.unpack('CvC')
if size == 0 or size.nil?
client.close
return
end
vars, sender = client.recvfrom(size)
if vars.length != size
client.close
return
end
env = Hash.new
i = 0
while i < size
kl = vars[i, 2].unpack('v')[0]
i = i + 2
key = vars[i, kl]
i = i + kl
vl = vars[i, 2].unpack('v')[0]
i = i + 2
value = vars[i, vl]
i = i + vl
env[key] = value
end
env.delete "HTTP_CONTENT_LENGTH"
env.delete "HTTP_CONTENT_TYPE"
env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
env["QUERY_STRING"] ||= ""
env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
env["REQUEST_PATH"] ||= "/"
env.delete "PATH_INFO" if env["PATH_INFO"] == ""
env.delete "CONTENT_TYPE" if env["CONTENT_TYPE"] == ""
env.delete "CONTENT_LENGTH" if env["CONTENT_LENGTH"] == ""
if env["CONTENT_LENGTH"].to_i > 4096
rack_input = Rack::RewindableInput::Tempfile.new('Rack_unbit_Input')
rack_input.chmod(0000)
rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding)
rack_input.binmode
rack_input.unlink
remains = env["CONTENT_LENGTH"].to_i
while remains > 0
if remains >= 4096
buf, sender = client.recvfrom(4096)
else
buf, sender = client.recvfrom(remains)
end
if buf.length == 0
break
end
rack_input.write( buf )
remains -= buf.length
end
elsif env["CONTENT_LENGTH"].to_i > 0
rack_input = StringIO.new(client.recvfrom(env["CONTENT_LENGTH"].to_i)[0])
else
rack_input = StringIO.new('')
end
rack_input.rewind
env.update({"rack.version" => [1,1],
"rack.input" => rack_input,
"rack.errors" => $stderr,
"rack.multithread" => false,
"rack.multiprocess" => true,
"rack.run_once" => false,
"rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http"
})
app = Rack::ContentLength.new(app)
disconnected = false
begin
status, headers, body = app.call(env)
begin
send_headers client, env["HTTP_VERSION"] ,status, headers
send_body client, body
ensure
body.close if body.respond_to? :close
end
rescue Errno::EPIPE, Errno::ECONNRESET
disconnected = true
ensure
rack_input.close
client.close
end
$requests = $requests+1
ulog("req: #{$requests} ip: #{env['REMOTE_ADDR']} pid: #{Process.pid} as: #{human_round(syscall(356).to_f/1024/1024)} MB => #{env['REQUEST_METHOD']} #{env['REQUEST_URI']} in #{Time.now-speed} secs [#{status}]#{' DISCONNECTED !!!' if disconnected}") if options[:logging]
end
def self.send_headers(client, protocol, status, headers)
client.print "#{protocol} #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]}\r\n"
headers.each { |k, vs|
vs.split("\n").each { |v|
client.print "#{k}: #{v}\r\n"
}
}
client.print "\r\n"
client.flush
end
def self.send_body(client, body)
body.each { |part|
client.print part
client.flush
}
end
end
end
end
def ulog(message)
$stderr.puts "[#{Time.new}] uRack: #{message}"
end
ulog("starting at #{Dir.getwd}")
limit_as = human_round(Process.getrlimit(Process::RLIMIT_AS)[1].to_f/1024/1024)
ulog("your process address space limit is #{limit_as} MB")
server = Rack::Handler.get('Unbit')
app = Rack::Builder.new {
if options[:serve_file]
puts "[#{Time.new}] uRack: file serving enabled."
use Rails::Rack::Static
starttime = Time.now
app = nil
if options[:config]
cfgfile = File.read(options[:config])
if cfgfile[/^#\\(.*)/]
opts.parse! $1.split(/\s+/)
end
if ActionController.const_defined?(:Dispatcher) && (ActionController::Dispatcher.instance_methods.include?(:call) || ActionController::Dispatcher.instance_methods.include?("call"))
run ActionController::Dispatcher.new
app = eval "Rack::Builder.new {( " + cfgfile + "\n )}.to_app", nil, options[:config]
else
# falling back to rails
if Dir.getwd =~ /\/public\/?$/
require '../config/environment'
else
require 'thin'
run Rack::Adapter::Rails.new(:environment => ENV['RAILS_ENV'])
require 'config/environment'
end
}.to_app
app = Rack::Builder.new {
if options[:cachehack]
use Rack::RailsCachingHack
end
if options[:static]
use Rails::Rack::Static
end
if ActionController.const_defined?(:Dispatcher) && (ActionController::Dispatcher.instance_methods.include?(:call) || ActionController::Dispatcher.instance_methods.include?("call"))
run ActionController::Dispatcher.new
else
require 'thin'
run Rack::Adapter::Rails.new(:environment => ENV['RAILS_ENV'])
end
}
end
$after_spawn_used_as = human_round(syscall(356).to_f/1024/1024)
$stderr.puts "#{$unbit_log_base} now you have #{$limit_as-$after_spawn_used_as} MB of address space available (used #{$after_spawn_used_as}MB after app startup)"
secs = Time.now-starttime
puts "[#{Time.new}] uRack: ready to serve requests after #{secs.to_i} secs (pid: #{Process.pid})"
ulog("your app is ready (in #{Time.now-starttime} seconds).")
$last_as = $after_spawn_used_as ;
$last_obj = ObjectSpace.each_object {}
server.run(app, options)
+30
View File
@@ -0,0 +1,30 @@
-module(uwsgi).
-export([encode/1,send/3]).
encode(Vars) ->
Body = lists:map(fun(X) -> Len = length(X), lists:append( binary_to_list(<<Len:16/little-unsigned-integer>>), X) end, Vars),
lists:flatten(Body).
response(Sock, Output) ->
case gen_tcp:recv(Sock,0) of
{ ok, Data } ->
response(Sock, lists:append(Output, binary_to_list(Data)));
{ error, closed } ->
gen_tcp:close(Sock),
Output
end.
send(Host, Port, Message) ->
{ ok, Sock } = gen_tcp:connect( Host, Port, [ binary, { active, false} ]),
Body = encode(Message),
Len = length(Body),
ok = gen_tcp:send(Sock, << 0, Len:16/little-unsigned-integer, 0>>),
ok = gen_tcp:send(Sock, Body),
response(Sock, []).
+27 -28
View File
@@ -6,7 +6,6 @@ import java.util.Enumeration;
import org.apache.catalina.util.IOTools;
public class uwsgi extends HttpServlet {
private String mountpoint = null;
public void init(ServletConfig config) throws ServletException {
@@ -22,34 +21,34 @@ public class uwsgi extends HttpServlet {
if (getServletConfig().getInitParameter("mountpoint") != null) {
mountpoint = getServletConfig().getInitParameter("mountpoint");
if (mountpoint.length() <= 1) {
mountpoint = null ;
mountpoint = null;
}
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
throws IOException, ServletException {
uWSGIHandler(request, response);
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
throws IOException, ServletException {
uWSGIHandler(request, response);
}
private void uWSGIHandler(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
throws IOException, ServletException {
Socket client = new Socket("localhost",3017);
ByteArrayOutputStream uwsgi_request = new ByteArrayOutputStream() ;
ByteArrayOutputStream uwsgi_request = new ByteArrayOutputStream();
DataOutputStream wos = new DataOutputStream(uwsgi_request);
DataOutputStream os = new DataOutputStream(client.getOutputStream());
DataInputStream is = new DataInputStream( client.getInputStream() );
ServletOutputStream out = response.getOutputStream();
boolean hasBody = false;
@@ -104,14 +103,14 @@ public class uwsgi extends HttpServlet {
if (mountpoint != null) {
wos.writeShort(swapShort( (short) 11));
wos.writeBytes("SCRIPT_NAME");
wos.writeShort(swapShort( (short) mountpoint.length() ) ) ;
wos.writeBytes( mountpoint ) ;
wos.writeBytes("SCRIPT_NAME");
wos.writeShort(swapShort( (short) mountpoint.length() ) );
wos.writeBytes( mountpoint );
}
wos.writeShort(swapShort( (short) 9));
wos.writeBytes("PATH_INFO");
wos.writeBytes("PATH_INFO");
if (mountpoint != null) {
wos.writeShort(swapShort( (short) (request.getRequestURI().length() - mountpoint.length()) ) );
wos.writeBytes( request.getRequestURI().substring(mountpoint.length()) );
@@ -149,14 +148,14 @@ public class uwsgi extends HttpServlet {
hasBody = true;
}
// taken from CGI servlet
Enumeration headers = request.getHeaderNames();
String header = null;
while (headers.hasMoreElements()) {
header = null;
header = ((String) headers.nextElement()).toUpperCase();
header = null;
header = ((String) headers.nextElement()).toUpperCase();
wos.writeShort(swapShort( (short) ("HTTP_" + header.replace('-', '_')).length() ));
wos.writeBytes("HTTP_" + header.replace('-', '_'));
wos.writeShort(swapShort( (short) request.getHeader(header).length() ));
@@ -175,16 +174,16 @@ public class uwsgi extends HttpServlet {
IOTools.flow(request.getInputStream(), os);
}
boolean statusParsed = false ;
boolean statusParsed = false;
for(;;) {
String line = byte_readline(is) ;
String line = byte_readline(is);
if (line == "") {
break;
}
if (statusParsed == false) {
String[] status = line.split(" ",3);
response.setStatus( Integer.parseInt(status[1]) );
statusParsed = true ;
statusParsed = true;
}
else {
String[] keyval = line.split(": ",2);
@@ -200,7 +199,7 @@ public class uwsgi extends HttpServlet {
byte cb[] = new byte[4096];
int len = 0;
for(;;) {
len = is.read(cb,0,4096) ;
len = is.read(cb,0,4096);
if ( len > 0) {
out.write(cb,0,len);
}
@@ -208,7 +207,7 @@ public class uwsgi extends HttpServlet {
break;
}
}
}
@@ -218,19 +217,19 @@ public class uwsgi extends HttpServlet {
for(;;) {
byte b = is.readByte();
if (b == 10) {
break ;
break;
}
line.write(b) ;
line.write(b);
}
return line.toString("ASCII").replaceAll("\\n","").replaceAll("\\r","");
}
private short swapShort(short x) {
short tmp1 = (short) (x>>8) ;
short tmp2 = (short) (x<<8) ;
return (short) (tmp1 | tmp2) ;
short tmp1 = (short) (x>>8);
short tmp2 = (short) (x<<8);
return (short) (tmp1 | tmp2);
}
}
+65 -65
View File
@@ -2,8 +2,8 @@
*** uWSGI cgi client ***
to compile:
gcc -Wall -o uwsgi_client.cgi uwsgi_client.c
to compile:
gcc -Wall -o uwsgi_client.cgi uwsgi_client.c
*/
@@ -18,79 +18,79 @@ to compile:
#define UWSGI_SOCK "/tmp/uwsgi.sock"
int main() {
extern char **environ;
char *env ;
struct sockaddr_un s_addr ;
int uwsgi_socket ;
int res, cnt;
char *place_holder;
unsigned short len ;
char message[4096];
char *mptr;
extern char **environ;
char *env;
struct sockaddr_un s_addr;
int uwsgi_socket;
int res, cnt;
char *place_holder;
unsigned short len;
char message[4096];
char *mptr;
char *content_length;
memset(&s_addr, 0, sizeof(struct sockaddr_un)) ;
memset(&s_addr, 0, sizeof(struct sockaddr_un));
s_addr.sun_family = AF_UNIX;
strcpy(s_addr.sun_path, UWSGI_SOCK);
s_addr.sun_family = AF_UNIX;
strcpy(s_addr.sun_path, UWSGI_SOCK);
uwsgi_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (uwsgi_socket < 0) {
perror("socket()");
exit(1);
}
uwsgi_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (uwsgi_socket < 0) {
perror("socket()");
exit(1);
}
if (connect(uwsgi_socket, (struct sockaddr *) &s_addr, strlen(UWSGI_SOCK) + ( (void *)&s_addr.sun_path - (void *)&s_addr) ) != 0) {
perror("connect()");
exit(1);
}
if (connect(uwsgi_socket, (struct sockaddr *) &s_addr, strlen(UWSGI_SOCK) + ( (void *)&s_addr.sun_path - (void *)&s_addr) ) != 0) {
perror("connect()");
exit(1);
}
memset(message, 0, 4096);
memset(message, 0, 4096);
mptr = message+4;
mptr = message+4;
if (**environ) {
while( (env = *environ) ) {
place_holder = strchr(env,'=');
// key
len = place_holder-env ;
memcpy(mptr, &len, 2);
mptr+=2;
memcpy(mptr, env, len);
mptr+=len ;
// value
len = (unsigned short) (env+strlen(env) - (place_holder+1)) ;
memcpy(mptr, &len, 2);
mptr+=2;
memcpy(mptr, place_holder+1, len);
mptr+= len ;
*environ++;
}
}
message[0] = 0;
len = (mptr-message)-4 ;
memcpy(message+1, &len, 2) ;
message[3] = 0 ;
res = send(uwsgi_socket, message, mptr-message, 0);
if ( (content_length = getenv("CONTENT_LENGTH")) != NULL) {
if (atoi(content_length) > 0) {
while( (cnt = read(0, message, 4096)) ) {
send(uwsgi_socket, message, cnt, 0) ;
}
if (**environ) {
while( (env = *environ) ) {
place_holder = strchr(env,'=');
// key
len = place_holder-env;
memcpy(mptr, &len, 2);
mptr+=2;
memcpy(mptr, env, len);
mptr+=len;
// value
len = (unsigned short) (env+strlen(env) - (place_holder+1));
memcpy(mptr, &len, 2);
mptr+=2;
memcpy(mptr, place_holder+1, len);
mptr+= len;
*environ++;
}
}
if (res == mptr-message) {
while( (res = recv(uwsgi_socket, message, 4096,0)) ) {
write(1, message, res) ;
}
}
return 0;
message[0] = 0;
len = (mptr-message)-4;
memcpy(message+1, &len, 2);
message[3] = 0;
res = send(uwsgi_socket, message, mptr-message, 0);
if ( (content_length = getenv("CONTENT_LENGTH")) != NULL) {
if (atoi(content_length) > 0) {
while( (cnt = read(0, message, 4096)) ) {
send(uwsgi_socket, message, cnt, 0);
}
}
}
if (res == mptr-message) {
while( (res = recv(uwsgi_socket, message, 4096,0)) ) {
write(1, message, res);
}
}
return 0;
}
+64 -64
View File
@@ -2,8 +2,8 @@
*** uWSGI cgi client ***
to compile:
gcc -Wall -o uwsgi_client.cgi uwsgi_dynamic_client.c
to compile:
gcc -Wall -o uwsgi_client.cgi uwsgi_dynamic_client.c
*/
@@ -19,77 +19,77 @@ to compile:
#define UWSGI_SCRIPT "myapp_wsgi"
int main() {
extern char **environ;
char *env ;
struct sockaddr_un s_addr ;
int uwsgi_socket ;
int res, cnt;
char *place_holder;
unsigned short len ;
char message[4096];
char *mptr;
extern char **environ;
char *env;
struct sockaddr_un s_addr;
int uwsgi_socket;
int res, cnt;
char *place_holder;
memset(&s_addr, 0, sizeof(struct sockaddr_un)) ;
unsigned short len;
char message[4096];
char *mptr;
s_addr.sun_family = AF_UNIX;
strcpy(s_addr.sun_path, UWSGI_SOCK);
memset(&s_addr, 0, sizeof(struct sockaddr_un));
uwsgi_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (uwsgi_socket < 0) {
perror("socket()");
exit(1);
}
s_addr.sun_family = AF_UNIX;
strcpy(s_addr.sun_path, UWSGI_SOCK);
if (connect(uwsgi_socket, (struct sockaddr *) &s_addr, strlen(UWSGI_SOCK) + ( (void *)&s_addr.sun_path - (void *)&s_addr) ) != 0) {
perror("connect()");
exit(1);
}
uwsgi_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (uwsgi_socket < 0) {
perror("socket()");
exit(1);
}
memset(message, 0, 4096);
if (connect(uwsgi_socket, (struct sockaddr *) &s_addr, strlen(UWSGI_SOCK) + ( (void *)&s_addr.sun_path - (void *)&s_addr) ) != 0) {
perror("connect()");
exit(1);
}
mptr = message+4;
if (setenv("UWSGI_SCRIPT", UWSGI_SCRIPT, 1) != 0) {
perror("setenv()");
exit(1);
}
if (**environ) {
while( (env = *environ) ) {
place_holder = strchr(env,'=');
// key
len = place_holder-env ;
memcpy(mptr, &len, 2);
mptr+=2;
memcpy(mptr, env, len);
mptr+=len ;
// value
len = (unsigned short) (env+strlen(env) - (place_holder+1)) ;
memcpy(mptr, &len, 2);
mptr+=2;
memcpy(mptr, place_holder+1, len);
mptr+= len ;
*environ++;
}
}
memset(message, 0, 4096);
message[0] = 0;
len = (mptr-message)-4 ;
memcpy(message+1, &len, 2) ;
message[3] = 0 ;
mptr = message+4;
if (setenv("UWSGI_SCRIPT", UWSGI_SCRIPT, 1) != 0) {
perror("setenv()");
exit(1);
}
if (**environ) {
while( (env = *environ) ) {
place_holder = strchr(env,'=');
// key
len = place_holder-env;
memcpy(mptr, &len, 2);
mptr+=2;
memcpy(mptr, env, len);
mptr+=len;
// value
len = (unsigned short) (env+strlen(env) - (place_holder+1));
memcpy(mptr, &len, 2);
mptr+=2;
memcpy(mptr, place_holder+1, len);
mptr+= len;
*environ++;
}
}
res = send(uwsgi_socket, message, mptr-message, 0);
message[0] = 0;
len = (mptr-message)-4;
memcpy(message+1, &len, 2);
message[3] = 0;
while( (cnt = read(0, message, 4096)) ) {
send(uwsgi_socket, message, cnt, 0) ;
}
res = send(uwsgi_socket, message, mptr-message, 0);
while( (cnt = read(0, message, 4096)) ) {
send(uwsgi_socket, message, cnt, 0);
}
if (res == mptr-message) {
while( (res = recv(uwsgi_socket, message, 4096,0)) ) {
write(1, message, res);
}
}
return 0;
if (res == mptr-message) {
while( (res = recv(uwsgi_socket, message, 4096,0)) ) {
write(1, message, res) ;
}
}
return 0;
}
-6
View File
@@ -1,6 +0,0 @@
Package: uwsgi
Version: 0.9.2
Maintainer: Unbit
Description: Fast, developer-friendly wsgi server
Architecture: i386
Depends: python2.5, libxml2
+21
View File
@@ -56,9 +56,30 @@
</table>
</div>
<div class="module" style="width:860px">
<table>
<caption style="width:860px">spooler jobs</caption>
<thead>
<tr>
<th scope="row">job filename</th>
<th scope="row">environment</th>
</tr>
</thead>
<tbody>
{% for j in jobs %}
<tr>
<td align="left">{{j.file}}</td>
<td align="left">{{j.env}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% if masterpid %}
<br/>
<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="reload/" method="post">
{% csrf_token %}
<input type="submit" value="gracefully reload uWSGI" name="_reload"/>
</form>
{% endif %}
+6
View File
@@ -14,12 +14,18 @@ def index(request):
w['load'] = (100 * (w['running_time']/1000))/total_load
w['last_spawn_str'] = time.ctime(w['last_spawn'])
spooler_jobs = uwsgi.spooler_jobs()
jobs = []
for j in spooler_jobs:
jobs.append({'file': j, 'env': uwsgi.parsefile(j)})
return render_to_response('uwsgi.html', {'masterpid': uwsgi.masterpid(),
'started_on': time.ctime(uwsgi.started_on),
'buffer_size': uwsgi.buffer_size,
'total_requests': uwsgi.total_requests(),
'numproc': uwsgi.numproc,
'workers': workers,
'jobs': jobs,
}, RequestContext(request, {}))
index = staff_member_required(index)
+512
View File
@@ -0,0 +1,512 @@
#include "uwsgi.h"
#include <glob.h>
extern struct uwsgi_server uwsgi;
extern char **environ;
struct uwsgi_instance {
struct uwsgi_instance *ui_prev;
struct uwsgi_instance *ui_next;
char name[0xff];
pid_t pid;
int status;
time_t born;
time_t last_mod;
uint64_t respawns;
int use_config;
int pipe[2];
int pipe_config[2];
char *config;
uint32_t config_len;
};
struct uwsgi_instance *ui;
struct uwsgi_instance *emperor_get(char *name) {
struct uwsgi_instance *c_ui = ui;
while (c_ui->ui_next) {
c_ui = c_ui->ui_next;
if (!strcmp(c_ui->name, name)) {
return c_ui;
}
}
return NULL;
}
void emperor_del(struct uwsgi_instance *c_ui) {
struct uwsgi_instance *parent_ui = c_ui->ui_prev;
struct uwsgi_instance *child_ui = c_ui->ui_next;
parent_ui->ui_next = child_ui;
if (child_ui) {
child_ui->ui_prev = parent_ui;
}
// this will destroy the whole uWSGI instance (and workers)
close(c_ui->pipe[0]);
if (c_ui->use_config) {
close(c_ui->pipe_config[0]);
}
uwsgi_log("removed uwsgi instance %s\n", c_ui->name);
free(c_ui);
}
void emperor_stop(struct uwsgi_instance *c_ui) {
// remove uWSGI instance
if (write(c_ui->pipe[0], "\0", 1) != 1) {
uwsgi_error("write()");
}
c_ui->status = 1;
uwsgi_log("stop the uwsgi instance %s\n", c_ui->name);
}
void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
// reload the uWSGI instance
if (c_ui->use_config) {
if (write(c_ui->pipe[0], "\0", 1) != 1) {
uwsgi_error("write()");
}
}
else {
if (write(c_ui->pipe[0], "\1", 1) != 1) {
uwsgi_error("write()");
}
}
c_ui->respawns++;
c_ui->last_mod = mod;
uwsgi_log("reload the uwsgi instance %s\n", c_ui->name);
}
void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
struct uwsgi_instance *c_ui = ui;
struct uwsgi_instance *n_ui = NULL;
pid_t pid;
char *argv[4];
char *uef;
char **uenvs;
while (c_ui->ui_next) {
c_ui = c_ui->ui_next;
}
n_ui = uwsgi_malloc(sizeof(struct uwsgi_instance));
memset(n_ui, 0, sizeof(struct uwsgi_instance));
if (config) {
n_ui->use_config = 1;
n_ui->config = config;
n_ui->config_len = config_size;
}
c_ui->ui_next = n_ui;
uwsgi_log("c_ui->ui_next = %p\n", c_ui->ui_next);
n_ui->ui_prev = c_ui;
memcpy(n_ui->name, name, strlen(name));
n_ui->born = born;
n_ui->last_mod = born;
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe)) {
uwsgi_error("socketpair()");
goto clear;
}
if (n_ui->use_config) {
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe_config)) {
uwsgi_error("socketpair()");
goto clear;
}
}
// a new uWSGI instance will start
pid = fork();
if (pid < 0) {
uwsgi_error("fork()")
}
else if (pid > 0) {
n_ui->pid = pid;
// close the right side of the pipe
close(n_ui->pipe[1]);
if (n_ui->use_config) {
close(n_ui->pipe_config[1]);
}
if (n_ui->use_config) {
if (write(n_ui->pipe_config[0], n_ui->config, n_ui->config_len) <= 0) {
uwsgi_error("write()");
}
close(n_ui->pipe_config[0]);
}
return;
}
else {
unsetenv("UWSGI_RELOADS");
uef = uwsgi_num2str(n_ui->pipe[1]);
if (setenv("UWSGI_EMPEROR_FD", uef, 1)) {
uwsgi_error("setenv()");
exit(1);
}
free(uef);
if (n_ui->use_config) {
uef = uwsgi_num2str(n_ui->pipe_config[1]);
if (setenv("UWSGI_EMPEROR_FD_CONFIG", uef, 1)) {
uwsgi_error("setenv()");
exit(1);
}
free(uef);
}
uenvs = environ;
while (*uenvs) {
if (!strncmp(*uenvs, "UWSGI_VASSAL_", 13)) {
char *ne = uwsgi_concat2("UWSGI_", *uenvs + 13);
char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0);
if (unsetenv(oe)) {
uwsgi_error("unsetenv()");
break;
}
free(oe);
uwsgi_log("putenv %s\n", ne);
if (putenv(ne)) {
uwsgi_error("putenv()");
}
// do not free ne as putenv will add it to the environ
uenvs = environ;
continue;
}
uenvs++;
}
// close the left side of the pipe
close(n_ui->pipe[0]);
if (n_ui->use_config) {
close(n_ui->pipe_config[0]);
}
// set args
argv[0] = uwsgi.binary_path;
if (!strcmp(name + (strlen(name) - 4), ".xml"))
argv[1] = "--xml";
if (!strcmp(name + (strlen(name) - 4), ".ini"))
argv[1] = "--ini";
if (!strcmp(name + (strlen(name) - 4), ".yml"))
argv[1] = "--yaml";
if (!strcmp(name + (strlen(name) - 5), ".yaml"))
argv[1] = "--yaml";
argv[2] = name;
argv[3] = NULL;
// start !!!
if (execvp(argv[0], argv)) {
uwsgi_error("execvp()");
}
// never here
exit(1);
}
clear:
free(n_ui);
c_ui->ui_next = NULL;
}
void emperor_loop() {
// monitor a directory
struct uwsgi_instance ui_base;
struct uwsgi_instance *ui_current;
struct stat st;
pid_t diedpid;
int waitpid_status;
int has_children = 0;
int i_am_alone = 0;
int simple_mode = 0;
glob_t g;
int i;
struct dirent *de;
char *amqp_port;
int amqp_fd = -1;
char *amqp_routing_key;
signal(SIGPIPE, SIG_IGN);
memset(&ui_base, 0, sizeof(struct uwsgi_instance));
uwsgi_log("*** starting uWSGI Emperor ***\n");
amqp_port = strchr(uwsgi.emperor_dir, ':');
if (amqp_port) {
reconnect:
while(amqp_fd == -1) {
uwsgi_log("connecting to AMQP server...\n");
amqp_fd = uwsgi_connect(uwsgi.emperor_dir, -1, 0);
if (amqp_fd < 0) {
sleep(1);
}
}
uwsgi_log("subscribing to queue...\n");
if (uwsgi_amqp_consume_queue(amqp_fd, "/", "", "uwsgi.emperor", "fanout") < 0) {
close(amqp_fd);
amqp_fd = -1;
goto reconnect;
}
}
else {
if (!glob(uwsgi.emperor_dir, GLOB_MARK, NULL, &g)) {
if (g.gl_pathc == 1 && g.gl_pathv[0][strlen(g.gl_pathv[0]) - 1] == '/') {
simple_mode = 1;
if (chdir(uwsgi.emperor_dir)) {
uwsgi_error("chdir()");
exit(1);
}
}
}
else {
uwsgi_error("glob()");
exit(1);
}
}
ui = &ui_base;
for (;;) {
if (!i_am_alone) {
diedpid = waitpid(uwsgi.emperor_pid, &waitpid_status, WNOHANG);
if (diedpid < 0 || diedpid > 0) {
i_am_alone = 1;
}
}
if (amqp_fd > -1) {
uint64_t msgsize;
if (uwsgi_waitfd(amqp_fd, 3)) {
char *config = uwsgi_amqp_consume(amqp_fd, &msgsize, &amqp_routing_key);
if (!config) {
uwsgi_log("problem with RabbitMQ server, trying reconnection...\n");
close(amqp_fd);
amqp_fd = -1;
goto reconnect;
}
if (amqp_routing_key) {
uwsgi_log("AMQP routing_key = %s\n", amqp_routing_key);
char *config_file = uwsgi_concat2("emperor://", amqp_routing_key);
free(amqp_routing_key);
ui_current = emperor_get(config_file);
if (ui_current) {
free(ui_current->config);
ui_current->config = config;
ui_current->config_len = msgsize;
if (!msgsize) {
emperor_del(ui_current);
}
else {
emperor_respawn(ui_current, time(NULL));
}
}
else {
if (msgsize > 0) {
emperor_add(config_file, time(NULL), config, msgsize);
}
}
free(config_file);
}
else {
if (msgsize) {
if (msgsize >= 0xff) { free(config); continue; }
uwsgi_log("%.*s\n", (int)msgsize, config);
char *config_file = uwsgi_concat2n(config, msgsize, "", 0);
free(config);
if (strncmp(config_file, "http://", 7)) {
if (stat(config_file, &st)) {
free(config_file);
continue;
}
if (!S_ISREG(st.st_mode)) {
free(config_file);
continue;
}
}
ui_current = emperor_get(config_file);
if (ui_current) {
emperor_respawn(ui_current, time(NULL));
}
else {
emperor_add(config_file, time(NULL), NULL, 0);
}
free(config_file);
}
}
}
}
else if (simple_mode) {
DIR *dir = opendir(".");
while ((de = readdir(dir)) != NULL) {
if (!strcmp(de->d_name + (strlen(de->d_name) - 4), ".xml") || !strcmp(de->d_name + (strlen(de->d_name) - 4), ".ini") || !strcmp(de->d_name + (strlen(de->d_name) - 4), ".yml") || !strcmp(de->d_name + (strlen(de->d_name) - 5), ".yaml")
) {
if (strlen(de->d_name) >= 0xff)
continue;
if (stat(de->d_name, &st))
continue;
if (!S_ISREG(st.st_mode))
continue;
ui_current = emperor_get(de->d_name);
if (ui_current) {
// check if mtime is changed and the uWSGI instance must be reloaded
if (st.st_mtime > ui_current->last_mod) {
emperor_respawn(ui_current, st.st_mtime);
}
}
else {
emperor_add(de->d_name, st.st_mtime, NULL, 0);
}
}
}
closedir(dir);
}
else {
if (glob(uwsgi.emperor_dir, GLOB_MARK, NULL, &g)) {
uwsgi_error("glob()");
continue;
}
for (i = 0; i < (int) g.gl_pathc; i++) {
if (!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 4), ".xml") ||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 4), ".ini") ||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 4), ".yml") ||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 5), ".yaml")
) {
if (strlen(g.gl_pathv[i]) >= 0xff)
continue;
if (stat(g.gl_pathv[i], &st))
continue;
if (!S_ISREG(st.st_mode))
continue;
ui_current = emperor_get(g.gl_pathv[i]);
if (ui_current) {
// check if mtime is changed and the uWSGI instance must be reloaded
if (st.st_mtime > ui_current->last_mod) {
emperor_respawn(ui_current, st.st_mtime);
}
}
else {
emperor_add(g.gl_pathv[i], st.st_mtime, NULL, 0);
}
}
}
}
// check for removed instances
ui_current = ui;
has_children = 0;
while (ui_current->ui_next) {
ui_current = ui_current->ui_next;
has_children++;
}
if (has_children) {
diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
}
else {
// vacuum
waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
diedpid = 0;
}
if (diedpid < 0) {
uwsgi_error("waitpid()");
}
ui_current = ui;
while (ui_current->ui_next) {
ui_current = ui_current->ui_next;
if (ui_current->status == 1) {
if (ui_current->config) free(ui_current->config);
emperor_del(ui_current);
break;
}
else if (!ui_current->use_config && strncmp(ui_current->name, "http://",7) && stat(ui_current->name, &st)) {
emperor_stop(ui_current);
}
else if (ui_current->pid == diedpid) {
if (ui_current->status == 0) {
// respawn an accidentally dead instance if its exit code is not UWSGI_EXILE_CODE
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_EXILE_CODE) {
emperor_del(ui_current);
}
else {
emperor_add(ui_current->name, ui_current->last_mod, ui_current->config, ui_current->config_len);
emperor_del(ui_current);
}
break;
}
else if (ui_current->status == 1) {
// remove 'marked for dead' instance
if (ui_current->config) free(ui_current->config);
emperor_del(ui_current);
break;
}
}
}
if (amqp_fd < 0)
sleep(3);
}
}
-702
View File
@@ -1,702 +0,0 @@
#ifdef UWSGI_ERLANG
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
static void erlang_log(void);
PyObject *py_erlang_connect(PyObject * self, PyObject * args) {
char *erlang_node;
int fd;
if (!PyArg_ParseTuple(args, "s:erlang_connect", &erlang_node)) {
return NULL;
}
UWSGI_SET_BLOCKING;
fd = erl_connect(erlang_node);
UWSGI_UNSET_BLOCKING;
return PyInt_FromLong(fd);
}
PyObject *py_erlang_recv_message(PyObject * self, PyObject * args) {
int erfd;
struct pollfd erpoll;
ErlMessage emsg;
PyObject *pyer = NULL;
unsigned char erlang_buffer[8192];
int eret;
int timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
if (!PyArg_ParseTuple(args, "i|i:erlang_recv_message", &erfd, &timeout)) {
return NULL;
}
if (erfd < 0) {
goto clear;
}
erpoll.fd = erfd;
erpoll.events = POLLIN;
cycle:
memset(&emsg, 0, sizeof(ErlMessage));
UWSGI_SET_BLOCKING;
if (timeout > 0) {
eret = poll(&erpoll, 1, timeout * 1000);
if (eret < 0) {
uwsgi_error("poll()");
goto clear;
}
else if (eret == 0) {
goto clear;
}
}
if (erl_receive_msg(erfd, erlang_buffer, 8192, &emsg) == ERL_MSG) {
if (emsg.type == ERL_TICK) {
goto cycle;
}
if (emsg.msg) {
pyer = eterm_to_py(emsg.msg);
}
if (emsg.msg) {
erl_free_compound(emsg.msg);
}
if (emsg.to) {
erl_free_compound(emsg.to);
}
if (emsg.from) {
erl_free_compound(emsg.from);
}
if (!pyer) {
goto clear;
}
UWSGI_UNSET_BLOCKING;
return pyer;
}
clear:
UWSGI_UNSET_BLOCKING;
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_erlang_send_message(PyObject * self, PyObject * args) {
ETERM *pymessage;
ETERM *pid;
int erfd;
PyObject *ermessage, *erdest, *zero;
int er_number, er_serial, er_creation;
char *er_node;
if (!PyArg_ParseTuple(args, "iOO|i:erlang_send_message", &erfd, &erdest, &ermessage)) {
return NULL;
}
if (erfd < 0) {
goto clear;
}
if (!PyString_Check(erdest) && !PyDict_Check(erdest)) {
goto clear;
}
pymessage = py_to_eterm(ermessage);
if (!pymessage) {
goto clear;
}
if (PyString_Check(erdest)) {
if (!erl_reg_send(erfd, PyString_AsString(erdest), pymessage)) {
erl_err_msg("erl_reg_send()");
goto clear2;
}
}
else if (PyDict_Check(erdest)) {
zero = PyDict_GetItemString(erdest, "node");
if (!zero) {
goto clear2;
}
if (!PyString_Check(zero)) {
goto clear2;
}
er_node = PyString_AsString(zero);
zero = PyDict_GetItemString(erdest, "number");
if (!zero) {
goto clear2;
}
if (!PyInt_Check(zero)) {
goto clear2;
}
er_number = PyInt_AsLong(zero);
zero = PyDict_GetItemString(erdest, "serial");
if (!zero) {
goto clear2;
}
if (!PyInt_Check(zero)) {
goto clear2;
}
er_serial = PyInt_AsLong(zero);
zero = PyDict_GetItemString(erdest, "creation");
if (!zero) {
goto clear2;
}
if (!PyInt_Check(zero)) {
goto clear2;
}
er_creation = PyInt_AsLong(zero);
pid = erl_mk_pid((const char *) er_node, er_number, er_serial, er_creation);
if (!pid) {
goto clear2;
}
if (!erl_send(erfd, pid, pymessage)) {
erl_err_msg("erl_send()");
erl_free_term(pid);
goto clear2;
}
erl_free_term(pid);
}
else {
goto clear;
}
erl_free_compound(pymessage);
Py_INCREF(Py_True);
return Py_True;
clear2:
erl_free_compound(pymessage);
clear:
PyErr_Print();
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_erlang_rpc(PyObject * self, PyObject * args) {
int fd, timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
char *emod, *efun;
PyObject *eargs, *pyer = NULL;
ETERM *pyargs, *rex;
ErlMessage emsg;
int eret;
if (!PyArg_ParseTuple(args, "issO|i:erlang_rpc", &fd, &emod, &efun, &eargs, &timeout)) {
return NULL;
}
if (fd < 0) {
goto clear;
}
pyargs = py_to_eterm(eargs);
if (!pyargs) {
goto clear;
}
if (erl_rpc_to(fd, emod, efun, pyargs)) {
erl_err_msg("erl_rpc_to()");
goto clear2;
}
cycle:
memset(&emsg, 0, sizeof(ErlMessage));
UWSGI_SET_BLOCKING;
eret = erl_rpc_from(fd, timeout * 1000, &emsg);
if (eret == ERL_TICK) {
goto cycle;
}
else if (eret == ERL_MSG) {
if (emsg.msg) {
if (ERL_IS_TUPLE(emsg.msg)) {
rex = erl_element(1, emsg.msg);
if (!rex) {
goto clear2;
}
if (!strncmp("rex", ERL_ATOM_PTR(rex), ERL_ATOM_SIZE(rex))) {
erl_free_term(rex);
rex = erl_element(2, emsg.msg);
if (!rex) {
goto clear2;
}
pyer = eterm_to_py(rex);
erl_free_term(rex);
}
else {
erl_free_term(rex);
}
}
}
if (emsg.msg) {
erl_free_compound(emsg.msg);
}
if (emsg.to) {
erl_free_compound(emsg.to);
}
if (emsg.from) {
erl_free_compound(emsg.from);
}
if (!pyer) {
goto clear2;
}
erl_free_compound(pyargs);
UWSGI_UNSET_BLOCKING;
return pyer;
}
else {
erl_err_msg("erl_rpc_from()");
}
clear2:
UWSGI_UNSET_BLOCKING;
erl_free_compound(pyargs);
clear:
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_erlang_close(PyObject * self, PyObject * args) {
int fd;
if (!PyArg_ParseTuple(args, "i:erlang_close", &fd)) {
return NULL;
}
if (fd >= 0) {
erl_close_connection(fd);
}
Py_INCREF(Py_True);
return Py_True;
}
static PyMethodDef uwsgi_erlang_methods[] = {
{"erlang_connect", py_erlang_connect, METH_VARARGS, ""},
{"erlang_send_message", py_erlang_send_message, METH_VARARGS, ""},
{"erlang_recv_message", py_erlang_recv_message, METH_VARARGS, ""},
{"erlang_rpc", py_erlang_rpc, METH_VARARGS, ""},
{"erlang_close", py_erlang_close, METH_VARARGS, ""},
{NULL, NULL},
};
int init_erlang(char *nodename, char *cookie) {
struct sockaddr_in e_addr;
char *ip;
char *node;
int efd;
int rlen;
char *cookiefile;
char *cookiehome;
char cookievalue[128];
int cookiefd;
PyMethodDef *uwsgi_function;
ip = strchr(nodename, '@');
if (ip == NULL) {
fprintf(stderr, "*** invalid erlang node name ***\n");
return -1;
}
if (cookie == NULL) {
// get the cookie from the home
cookiehome = getenv("HOME");
if (!cookiehome) {
fprintf(stderr, "unable to get erlang cookie from your home.\n");
return -1;
}
cookiefile = malloc(strlen(cookiehome) + 1 + strlen(".erlang.cookie") + 1);
if (!cookiefile) {
uwsgi_error("malloc()");
}
cookiefile[0] = 0;
strcat(cookiefile, cookiehome);
strcat(cookiefile, "/.erlang.cookie");
cookiefd = open(cookiefile, O_RDONLY);
if (cookiefd < 0) {
uwsgi_error("open()");
free(cookiefile);
return -1;
}
memset(cookievalue, 0, 128);
if (read(cookiefd, cookievalue, 127) < 1) {
fprintf(stderr, "invalid cookie found in %s\n", cookiefile);
close(cookiefd);
free(cookiefile);
return -1;
}
cookie = cookievalue;
close(cookiefd);
free(cookiefile);
}
node = malloc((ip - nodename) + 1);
if (node == NULL) {
uwsgi_error("malloc()");
return -1;
}
memset(node, 0, (ip - nodename) + 1);
memcpy(node, nodename, ip - nodename);
erl_init(NULL, 0);
if (erl_connect_xinit(ip + 1, node, nodename, NULL, cookie, 0) == -1) {
fprintf(stderr, "*** unable to initialize erlang c-node ***\n");
return -1;
}
efd = socket(AF_INET, SOCK_STREAM, 0);
if (efd < 0) {
uwsgi_error("socket()");
return -1;
}
memset(&e_addr, 0, sizeof(struct sockaddr_in));
e_addr.sin_family = AF_INET;
e_addr.sin_addr.s_addr = inet_addr(ip + 1);
rlen = 1;
if (setsockopt(efd, SOL_SOCKET, SO_REUSEADDR, &rlen, sizeof(rlen))) {
uwsgi_error("setsockopt()");
close(efd);
return -1;
}
if (bind(efd, (struct sockaddr *) &e_addr, sizeof(struct sockaddr_in)) < 0) {
uwsgi_error("bind()");
close(efd);
return -1;
}
rlen = sizeof(struct sockaddr_in);
if (getsockname(efd, (struct sockaddr *) &e_addr, (socklen_t *) & rlen)) {
uwsgi_error("getsockname()");
close(efd);
return -1;
}
if (listen(efd, uwsgi.listen_queue)) {
uwsgi_error("listen()");
close(efd);
return -1;
}
if (erl_publish(ntohs(e_addr.sin_port)) < 0) {
fprintf(stderr, "*** unable to subscribe with EPMD ***\n");
close(efd);
return -1;
}
fprintf(stderr, "Erlang C-Node initialized on port %d you can access it with name %s\n", ntohs(e_addr.sin_port), nodename);
for (uwsgi_function = uwsgi_erlang_methods; uwsgi_function->ml_name != NULL; uwsgi_function++) {
PyObject *func = PyCFunction_New(uwsgi_function, NULL);
PyDict_SetItemString(uwsgi.embedded_dict, uwsgi_function->ml_name, func);
Py_DECREF(func);
}
return efd;
}
ETERM *py_to_eterm(PyObject * pobj) {
int i;
int count;
PyObject *pobj2;
ETERM *eobj = NULL;
ETERM *eobj2 = NULL;
ETERM **eobj3;
if (pobj == NULL) {
return erl_mk_empty_list();
}
if (PyString_Check(pobj)) {
eobj = erl_mk_atom(PyString_AsString(pobj));
}
else if (PyInt_Check(pobj)) {
eobj = erl_mk_int(PyInt_AsLong(pobj));
}
else if (PyList_Check(pobj)) {
eobj = erl_mk_empty_list();
for (i = PyList_Size(pobj) - 1; i >= 0; i--) {
pobj2 = PyList_GetItem(pobj, i);
eobj2 = py_to_eterm(pobj2);
eobj = erl_cons(eobj2, eobj);
}
}
else if (PyDict_Check(pobj)) {
// a pid
char *er_node;
int er_number, er_serial, er_creation;
pobj2 = PyDict_GetItemString(pobj, "node");
if (!pobj2) {
PyErr_Print();
goto clear;
}
if (!PyString_Check(pobj2)) {
goto clear;
}
er_node = PyString_AsString(pobj2);
pobj2 = PyDict_GetItemString(pobj, "number");
if (!pobj2) {
PyErr_Print();
goto clear;
}
if (!PyInt_Check(pobj2)) {
goto clear;
}
er_number = PyInt_AsLong(pobj2);
pobj2 = PyDict_GetItemString(pobj, "serial");
if (!pobj2) {
PyErr_Print();
goto clear;
}
if (!PyInt_Check(pobj2)) {
goto clear;
}
er_serial = PyInt_AsLong(pobj2);
pobj2 = PyDict_GetItemString(pobj, "creation");
if (!pobj2) {
PyErr_Print();
goto clear;
}
if (!PyInt_Check(pobj2)) {
goto clear;
}
er_creation = PyInt_AsLong(pobj2);
eobj = erl_mk_pid(er_node, er_number, er_serial, er_creation);
}
else if (PyTuple_Check(pobj)) {
count = PyTuple_Size(pobj);
eobj3 = malloc(sizeof(ETERM *) * count);
for (i = 0; i < count; i++) {
pobj2 = PyTuple_GetItem(pobj, i);
if (!pobj2) {
break;
}
eobj3[i] = py_to_eterm(pobj2);
}
eobj = erl_mk_tuple(eobj3, count);
free(eobj3);
}
else {
fprintf(stderr, "UNMANAGED PYTHON TYPE: %s\n", pobj->ob_type->tp_name);
}
clear:
if (eobj == NULL) {
return erl_mk_empty_list();
}
return eobj;
}
PyObject *eterm_to_py(ETERM * obj) {
int i;
int count;
ETERM *obj2;
PyObject *eobj = NULL;
if (obj == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
switch (ERL_TYPE(obj)) {
case ERL_CONS:
case ERL_NIL:
count = erl_length(obj);
eobj = PyList_New(0);
for (i = 0; i < count; i++) {
obj2 = erl_hd(obj);
PyList_Append(eobj, eterm_to_py(obj2));
obj = erl_tl(obj);
}
break;
case ERL_TUPLE:
eobj = PyTuple_New(erl_size(obj));
for (i = 1; i <= erl_size(obj); i++) {
obj2 = erl_element(i, obj);
PyTuple_SetItem(eobj, i - 1, eterm_to_py(obj2));
}
break;
case ERL_ATOM:
eobj = PyString_FromStringAndSize(ERL_ATOM_PTR(obj), ERL_ATOM_SIZE(obj));
break;
case ERL_INTEGER:
eobj = PyInt_FromLong(ERL_INT_VALUE(obj));
break;
case ERL_BINARY:
fprintf(stderr, "FOUND A BINARY %.*s\n", ERL_BIN_SIZE(obj), ERL_BIN_PTR(obj));
break;
case ERL_PID:
eobj = PyDict_New();
if (PyDict_SetItemString(eobj, "node", PyString_FromString(ERL_PID_NODE(obj)))) {
PyErr_Print();
break;
}
if (PyDict_SetItemString(eobj, "number", PyInt_FromLong(ERL_PID_NUMBER(obj)))) {
PyErr_Print();
break;
}
if (PyDict_SetItemString(eobj, "serial", PyInt_FromLong(ERL_PID_SERIAL(obj)))) {
PyErr_Print();
break;
}
if (PyDict_SetItemString(eobj, "creation", PyInt_FromLong(ERL_PID_CREATION(obj)))) {
PyErr_Print();
break;
}
default:
fprintf(stderr, "UNMANAGED ETERM TYPE: %d\n", ERL_TYPE(obj));
break;
}
if (eobj == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
return eobj;
}
void erlang_loop(struct wsgi_request *wsgi_req) {
ErlConnect econn;
ErlMessage em;
ETERM *eresponse;
PyObject *callable = PyDict_GetItemString(uwsgi.embedded_dict, "erlang_func");
if (!callable) {
PyErr_Print();
fprintf(stderr, "- you have not defined a uwsgi.erlang_func callable, Erlang message manager will be disabled until you define it -\n");
}
PyObject *pargs = PyTuple_New(1);
if (!pargs) {
PyErr_Print();
fprintf(stderr, "- error preparing arg tuple for uwsgi.erlang_func callable, Erlang message manager will be disabled -\n");
}
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
UWSGI_CLEAR_STATUS;
wsgi_req->poll.fd = erl_accept(uwsgi.erlangfd, &econn);
if (wsgi_req->poll.fd >= 0) {
UWSGI_SET_ERLANGING;
for (;;) {
if (erl_receive_msg(wsgi_req->poll.fd, (unsigned char *) wsgi_req->buffer, uwsgi.buffer_size, &em) == ERL_MSG) {
if (em.type == ERL_TICK)
continue;
if (!callable) {
callable = PyDict_GetItemString(uwsgi.embedded_dict, "erlang_func");
}
if (!callable) {
fprintf(stderr, "- you still have not defined a uwsgi.erlang_func callable, Erlang message rejected -\n");
}
PyObject *zero = eterm_to_py(em.msg);
if (em.msg) {
erl_free_compound(em.msg);
}
if (em.to) {
erl_free_compound(em.to);
}
if (!zero) {
PyErr_Print();
continue;
}
if (PyTuple_SetItem(pargs, 0, zero)) {
PyErr_Print();
continue;
}
PyObject *erlang_result = PyEval_CallObject(callable, pargs);
//Py_DECREF(zero);
if (erlang_result) {
eresponse = py_to_eterm(erlang_result);
if (eresponse) {
erl_send(wsgi_req->poll.fd, em.from, eresponse);
erl_free_compound(eresponse);
}
Py_DECREF(erlang_result);
}
if (em.from) {
erl_free_compound(em.from);
}
uwsgi.workers[0].requests++;
uwsgi.workers[uwsgi.mywid].requests++;
if (uwsgi.shared->options[UWSGI_OPTION_LOGGING])
erlang_log();
}
else {
break;
}
}
erl_close_connection(wsgi_req->poll.fd);
UWSGI_UNSET_ERLANGING;
}
}
}
static void erlang_log() {
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG]) {
get_memusage();
}
else {
uwsgi.workers[uwsgi.mywid].rss_size = 0;
uwsgi.workers[uwsgi.mywid].vsz_size = 0;
}
fprintf(stderr, "[Erlang worker %d pid %d] request %llu done {rss: %llu vsz: %llu}\n", uwsgi.mywid, uwsgi.mypid, uwsgi.workers[uwsgi.mywid].requests, uwsgi.workers[uwsgi.mywid].rss_size, uwsgi.workers[uwsgi.mywid].vsz_size);
}
#else
#warning "*** Erlang support is disabled ***"
#endif
+22
View File
@@ -0,0 +1,22 @@
#ifdef UWSGI_EVDIS
#include "uwsgi.h"
void evdis_loop(struct uwsgi_server *uwsgi) {
// populate event list
int kfd = kqueue();
if (kfd < 0) {
uwsgi_error("kqueue()");
exit(1);
}
}
#else
#warning "*** Event Dispatcher support is disabled ***"
#endif
+854
View File
@@ -0,0 +1,854 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_EVENT_USE_PORT
#include <port.h>
#define UWSGI_EVENT_IN POLLIN
#define UWSGI_EVENT_OUT POLLOUT
int event_queue_init() {
int port = port_create();
if (port < 0) {
uwsgi_error("port_create()");
return -1;
}
return port;
}
int event_queue_del_fd(int eq, int fd, int event) {
if (port_dissociate(eq, PORT_SOURCE_FD, fd)) {
uwsgi_error("port_disassociate");
return -1;
}
return fd;
}
int event_queue_fd_write_to_read(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
uwsgi_error("port_associate");
return -1;
}
return fd;
}
int event_queue_interesting_fd_has_error(void *events, int id) {
port_event_t *pe = (port_event_t *) events;
if (pe[id].portev_events == POLLHUP || pe[id].portev_events == POLLERR) {
return 1;
}
return 0;
}
int event_queue_add_fd_read(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
uwsgi_error("port_associate");
return -1;
}
return fd;
}
int event_queue_add_fd_write(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
uwsgi_error("port_associate");
return -1;
}
return fd;
}
void *event_queue_alloc(int nevents) {
return uwsgi_malloc(sizeof(port_event_t) * nevents);
}
int event_queue_interesting_fd(void *events, int id) {
port_event_t *pe = (port_event_t *) events;
if (pe[id].portev_source == PORT_SOURCE_FILE || pe[id].portev_source == PORT_SOURCE_TIMER) {
return (int) pe[id].portev_user;
}
return (int) pe[id].portev_object;
}
int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
int ret;
uint_t nget = 1;
timespec_t ts;
port_event_t *pe;
if (timeout >= 0) {
ts.tv_sec = timeout;
ts.tv_nsec = 0;
ret = port_getn(eq, events, nevents, &nget, &ts);
}
else {
ret = port_getn(eq, events, nevents, &nget, NULL);
}
if (ret < 0) {
if (errno != ETIME) {
uwsgi_error("port_getn()");
return -1;
}
return 0;
}
pe = (port_event_t *) events;
return nget;
}
int event_queue_wait(int eq, int timeout, int *interesting_fd) {
int ret;
port_event_t pe;
timespec_t ts;
if (timeout > 0) {
ts.tv_sec = timeout;
ts.tv_nsec = 0;
ret = port_get(eq, &pe, &ts);
}
else {
ret = port_get(eq, &pe, NULL);
}
if (ret < 0) {
if (errno != ETIME) {
uwsgi_error("port_get()");
return -1;
}
return 0;
}
if (pe.portev_source == PORT_SOURCE_FD) {
// event must be readded (damn Oracle/Sun why the fu*k you made such a horrible choice ???? why not adding a ONESHOT flag ???)
if (port_associate(eq, pe.portev_source, pe.portev_object, pe.portev_events, NULL)) {
uwsgi_error("port_associate");
}
}
if (pe.portev_source == PORT_SOURCE_FILE || pe.portev_source == PORT_SOURCE_TIMER) {
*interesting_fd = (int) pe.portev_user;
}
else {
*interesting_fd = (int) pe.portev_object;
}
return 1;
}
#endif
#ifdef UWSGI_EVENT_USE_EPOLL
#include <sys/epoll.h>
#define UWSGI_EVENT_IN EPOLLIN
#define UWSGI_EVENT_OUT EPOLLOUT
int event_queue_init() {
int epfd;
epfd = epoll_create(256);
if (epfd < 0) {
uwsgi_error("epoll_create()");
return -1;
}
return epfd;
}
int event_queue_add_fd_read(int eq, int fd) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = EPOLLIN;
ee.data.fd = fd;
if (epoll_ctl(eq, EPOLL_CTL_ADD, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
}
return fd;
}
int event_queue_fd_write_to_read(int eq, int fd) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = EPOLLIN;
ee.data.fd = fd;
if (epoll_ctl(eq, EPOLL_CTL_MOD, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
}
return fd;
}
int event_queue_del_fd(int eq, int fd, int event) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.data.fd = fd;
ee.events = event;
if (epoll_ctl(eq, EPOLL_CTL_DEL, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
}
return fd;
}
int event_queue_add_fd_write(int eq, int fd) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = EPOLLOUT;
ee.data.fd = fd;
if (epoll_ctl(eq, EPOLL_CTL_ADD, fd, &ee)) {
uwsgi_error("epoll_ctl()");
return -1;
}
return fd;
}
void *event_queue_alloc(int nevents) {
return uwsgi_malloc(sizeof(struct epoll_event) * nevents);
}
int event_queue_interesting_fd(void *events, int id) {
struct epoll_event *ee = (struct epoll_event *) events;
return ee[id].data.fd;
}
int event_queue_interesting_fd_has_error(void *events, int id) {
struct epoll_event *ee = (struct epoll_event *) events;
if (ee[id].events == EPOLLHUP || ee[id].events == EPOLLERR || (ee[id].events == (EPOLLERR|EPOLLHUP))) {
return 1;
}
return 0;
}
int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
int ret;
if (timeout > 0) {
timeout = timeout*1000;
}
ret = epoll_wait(eq, (struct epoll_event *) events, nevents, timeout);
if (ret < 0) {
if (errno != EINTR)
uwsgi_error("epoll_wait()");
}
return ret;
}
int event_queue_wait(int eq, int timeout, int *interesting_fd) {
int ret;
struct epoll_event ee;
if (timeout > 0) {
timeout = timeout*1000;
}
ret = epoll_wait(eq, &ee, 1, timeout);
if (ret < 0) {
if (errno != EINTR)
uwsgi_error("epoll_wait()");
}
if (ret > 0) {
*interesting_fd = ee.data.fd;
}
return ret;
}
#endif
#ifdef UWSGI_EVENT_USE_KQUEUE
#define UWSGI_EVENT_IN EVFILT_READ
#define UWSGI_EVENT_OUT EVFILT_WRITE
int event_queue_init() {
int kfd = kqueue();
if (kfd < 0) {
uwsgi_error("kqueue()");
return -1;
}
return kfd;
}
int event_queue_fd_write_to_read(int eq, int fd) {
struct kevent kev;
EV_SET(&kev, fd, EVFILT_WRITE, EV_DISABLE, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
EV_SET(&kev, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return fd;
}
int event_queue_del_fd(int eq, int fd, int event) {
struct kevent kev;
EV_SET(&kev, fd, event, EV_DELETE, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return fd;
}
int event_queue_add_fd_read(int eq, int fd) {
struct kevent kev;
EV_SET(&kev, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return fd;
}
int event_queue_add_fd_write(int eq, int fd) {
struct kevent kev;
EV_SET(&kev, fd, EVFILT_WRITE, EV_ADD, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return 0;
}
void *event_queue_alloc(int nevents) {
return uwsgi_malloc(sizeof(struct kevent) * nevents);
}
int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
int ret;
struct timespec ts;
if (timeout < 0) {
ret = kevent(eq, NULL, 0, events, nevents, NULL);
}
else {
memset(&ts, 0, sizeof(struct timespec));
ts.tv_sec = timeout;
ret = kevent(eq, NULL, 0, (struct kevent *)events, nevents, &ts);
}
if (ret < 0) {
uwsgi_error("kevent()");
}
return ret;
}
int event_queue_interesting_fd(void *events, int id) {
struct kevent *ev = (struct kevent *) events;
return ev[id].ident;
}
int event_queue_interesting_fd_has_error(void *events, int id) {
struct kevent *ev = (struct kevent *) events;
if ( ( (ev[id].flags == EV_ERROR) || (ev[id].flags == EV_EOF) || (ev[id].flags == (EV_EOF|EV_ERROR))) ) {
return 1;
}
return 0;
}
int event_queue_wait(int eq, int timeout, int *interesting_fd) {
int ret;
struct timespec ts;
struct kevent ev;
if (timeout <= 0) {
ret = kevent(eq, NULL, 0, &ev, 1, NULL);
}
else {
memset(&ts, 0, sizeof(struct timespec));
ts.tv_sec = timeout;
ret = kevent(eq, NULL, 0, &ev, 1, &ts);
}
if (ret < 0) {
uwsgi_error("kevent()");
}
if (ret > 0) {
*interesting_fd = ev.ident;
}
return ret;
}
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_NONE
int event_queue_add_file_monitor(int eq, char *filename, int *id) { return -1;}
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {return NULL;}
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_PORT
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
struct file_obj fo;
struct stat st;
static int fmon_id = 0xffffee00;
if (stat(filename, &st)) {
uwsgi_error("stat()");
return -1;
}
fo.fo_name = filename;
fo.fo_atime = st.st_atim;
fo.fo_mtime = st.st_mtim;
fo.fo_ctime = st.st_ctim;
fmon_id++;
if (port_associate(eq, PORT_SOURCE_FILE, (uintptr_t) &fo, FILE_MODIFIED|FILE_ATTRIB, (void *) fmon_id)) {
uwsgi_error("port_associate()");
return -1;
}
*id = fmon_id;
uwsgi_log("added new file to monitor %s [%d]\n", filename, *id);
return *id;
}
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
int i;
struct file_obj fo;
struct stat st;
for(i=0;i<ushared->files_monitored_cnt;i++) {
if (ushared->files_monitored[i].registered) {
if (ushared->files_monitored[i].fd == id) {
if (stat(ushared->files_monitored[i].filename, &st)) {
uwsgi_error("stat()");
return NULL;
}
fo.fo_name = ushared->files_monitored[i].filename;
fo.fo_atime = st.st_atim;
fo.fo_mtime = st.st_mtim;
fo.fo_ctime = st.st_ctim;
if (port_associate(eq, PORT_SOURCE_FILE, (uintptr_t) &fo, FILE_MODIFIED|FILE_ATTRIB, (void *)id)) {
uwsgi_error("port_associate()");
return NULL;
}
return &ushared->files_monitored[i];
}
}
}
return NULL;
}
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_KQUEUE
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
struct kevent kev;
int fd = open(filename, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(filename);
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(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
*id = fd;
uwsgi_log("added new file to monitor %s\n", filename);
return fd;
}
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
int i;
for(i=0;i<ushared->files_monitored_cnt;i++) {
if (ushared->files_monitored[i].registered) {
if (ushared->files_monitored[i].fd == id) {
return &ushared->files_monitored[i];
}
}
}
return NULL;
}
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
#include <sys/inotify.h>
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
int ifd = -1;
int i;
int add_to_queue = 0;
for (i=0;i<ushared->files_monitored_cnt;i++) {
if (ushared->files_monitored[i].registered) {
ifd = ushared->files_monitored[0].fd;
break;
}
}
if (ifd == -1) {
ifd = inotify_init();
if (ifd < 0) {
uwsgi_error("inotify_init()");
return -1;
}
add_to_queue = 1;
}
*id = inotify_add_watch(ifd, filename, IN_ATTRIB|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MODIFY|IN_MOVE_SELF|IN_MOVED_FROM|IN_MOVED_TO);
uwsgi_log("added watch %d for filename %s\n", *id, filename);
if (add_to_queue) {
return event_queue_add_fd_read(eq, ifd);
}
else {
return ifd;
}
}
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
ssize_t rlen = 0;
struct inotify_event ie, *bie, *iie;
int i,j;
int items = 0;
unsigned int isize = sizeof(struct inotify_event);
struct uwsgi_fmon *uf = NULL;
if (ioctl(id, FIONREAD, &isize) < 0) {
uwsgi_error("ioctl()");
return NULL;
}
if (isize > sizeof(struct inotify_event)) {
bie = uwsgi_malloc(isize);
rlen = read(id, bie, isize);
}
else {
rlen = read(id, &ie, sizeof(struct inotify_event));
bie = &ie;
}
if (rlen < 0) {
uwsgi_error("read()");
}
else {
items = isize/(sizeof(struct inotify_event));
uwsgi_log("inotify returned %d items\n", items);
for(j=0;j<items;j++) {
iie = &bie[j];
for(i=0;i<ushared->files_monitored_cnt;i++) {
if (ushared->files_monitored[i].registered) {
if (ushared->files_monitored[i].fd == id && ushared->files_monitored[i].id == iie->wd) {
uf = &ushared->files_monitored[i];
}
}
}
}
if (items > 1) {
free(bie);
}
return uf;
}
return NULL;
}
#endif
#ifdef UWSGI_EVENT_TIMER_USE_TIMERFD
#ifndef UWSGI_EVENT_TIMER_USE_TIMERFD_NOINC
#include <sys/timerfd.h>
#endif
#ifndef TFD_CLOEXEC
// timerfd support
enum
{
TFD_CLOEXEC = 02000000,
#define TFD_CLOEXEC TFD_CLOEXEC
TFD_NONBLOCK = 04000
#define TFD_NONBLOCK TFD_NONBLOCK
};
/* Bits to be set in the FLAGS parameter of `timerfd_settime'. */
enum
{
TFD_TIMER_ABSTIME = 1 << 0
#define TFD_TIMER_ABSTIME TFD_TIMER_ABSTIME
};
static int timerfd_create (clockid_t __clock_id, int __flags) {
return syscall(322, __clock_id, __flags);
}
static int timerfd_settime (int __ufd, int __flags,
__const struct itimerspec *__utmr,
struct itimerspec *__otmr) {
return syscall(325, __ufd, __flags, __utmr, __otmr);
}
#endif
int event_queue_add_timer(int eq, int *id, int sec) {
struct itimerspec it;
int tfd = timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC);
if (tfd < 0) {
uwsgi_error("timerfd_create()");
return -1;
}
it.it_value.tv_sec = sec;
it.it_value.tv_nsec = 0;
it.it_interval.tv_sec = sec;
it.it_interval.tv_nsec = 0;
if (timerfd_settime(tfd, 0, &it, NULL)) {
uwsgi_error("timerfd_settime()");
close(tfd);
return -1;
}
*id = tfd;
return event_queue_add_fd_read(eq, tfd);
}
struct uwsgi_timer *event_queue_ack_timer(int id) {
int i;
ssize_t rlen;
uint64_t counter;
struct uwsgi_timer *ut = NULL;
for(i=0;i<ushared->timers_cnt;i++) {
if (ushared->timers[i].registered) {
if (ushared->timers[i].id == id) {
ut = &ushared->timers[i];
}
}
}
rlen = read(id, &counter, sizeof(uint64_t));
if (rlen < 0) {
uwsgi_error("read()");
}
return ut;
}
#endif
#ifdef UWSGI_EVENT_TIMER_USE_NONE
int event_queue_add_timer(int eq, int *id, int sec) { return -1; }
struct uwsgi_timer *event_queue_ack_timer(int id) { return NULL;}
#endif
#ifdef UWSGI_EVENT_TIMER_USE_PORT
int event_queue_add_timer(int eq, int *id, int sec) {
static int timer_id = 0xffffff00;
port_notify_t pnotif;
struct sigevent sigev;
itimerspec_t it;
timer_t tid;
timer_id++;
pnotif.portnfy_port = eq;
pnotif.portnfy_user = (void *) timer_id;
sigev.sigev_notify = SIGEV_PORT;
sigev.sigev_value.sival_ptr = &pnotif;
if (timer_create(CLOCK_REALTIME, &sigev, &tid) < 0) {
uwsgi_error("timer_create()");
return -1;
}
it.it_value.tv_sec = sec;
it.it_value.tv_nsec = 0;
it.it_interval.tv_sec = sec;
it.it_interval.tv_nsec = 0;
if (timer_settime(tid, 0, &it, NULL) < 0) {
uwsgi_error("timer_settime()");
return -1;
}
*id = timer_id;
return *id;
}
struct uwsgi_timer *event_queue_ack_timer(int id) {
int i;
struct uwsgi_timer *ut = NULL;
for(i=0;i<uwsgi.shared->timers_cnt;i++) {
if (uwsgi.shared->timers[i].registered) {
if (uwsgi.shared->timers[i].id == id) {
ut = &uwsgi.shared->timers[i];
}
}
}
return ut;
}
#endif
#ifdef UWSGI_EVENT_TIMER_USE_KQUEUE
int event_queue_add_timer(int eq, int *id, int sec) {
static int timer_id = 0xffffff00;
struct kevent kev;
*id = timer_id ;
timer_id++;
uwsgi_log("registering timer %d\n", sec);
EV_SET(&kev, *id, EVFILT_TIMER, EV_ADD, 0, sec*1000, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
}
return *id;
}
struct uwsgi_timer *event_queue_ack_timer(int id) {
int i;
struct uwsgi_timer *ut = NULL;
for(i=0;i<uwsgi.shared->timers_cnt;i++) {
if (uwsgi.shared->timers[i].registered) {
if (uwsgi.shared->timers[i].id == id) {
ut = &uwsgi.shared->timers[i];
}
}
}
return ut;
}
#endif
inline int event_queue_read() {
return UWSGI_EVENT_IN;
}
inline int event_queue_write() {
return UWSGI_EVENT_OUT;
}
+21
View File
@@ -0,0 +1,21 @@
require 'fiber'
class SuspendingBody
def each
for i in 1..10
yield "number: #{i}\n"
Fiber.yield
end
end
end
class RackFoo
def call(env)
[200, { 'Content-Type' => 'text/plain'}, SuspendingBody.new]
end
end
run RackFoo.new
+8
View File
@@ -0,0 +1,8 @@
uwsgi:
plugins: rack
socket: 127.0.0.1:3031
rack: fibers.ru
post-buffering: 4096
async: 10
loop: fiber
+34
View File
@@ -0,0 +1,34 @@
#ifdef __linux__
#include <sys/inotify.h>
int uwsgi_file_monitor_new() {
int inotify_fd;
inotify_fd = inotify_init();
if (inotify_fd < 0) {
uwsgi_error("inotify_init()");
return -1;
}
return inotify_fd;
}
int uwsgi_file_monitor_add(int fd, char *what) {
int inotify_watch_fd;
inotify_watch_fd = inotify_add_watch(fd, what, IN_ALL_EVENTS);
if (inotify_watch_fd < 0) {
uwsgi_error("inotify_add_watch()");
return -1;
}
return inotify_watch_fd;
}
#endif
+122
View File
@@ -0,0 +1,122 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
struct uwsgi_gateway *register_fat_gateway(char *name, void (*loop)(void)) {
struct uwsgi_gateway *ug;
int num=1,i;
if (uwsgi.gateways_cnt >= MAX_GATEWAYS) {
uwsgi_log("you can register max %d gateways\n", MAX_GATEWAYS);
return NULL;
}
for(i=0;i<uwsgi.gateways_cnt;i++) {
if (!strcmp(name, uwsgi.gateways[i].name)) {
num++;
}
}
ug = &uwsgi.gateways[uwsgi.gateways_cnt];
ug->pid = 0;
ug->name = name;
ug->loop = loop;
ug->num = num;
uwsgi.gateways_cnt++;
return ug;
}
struct uwsgi_gateway *register_gateway(char *name, void (*loop)(void)) {
pid_t gw_pid;
pid_t orig_pid = getpid();
struct uwsgi_gateway *ug;
int num=1,i;
if (uwsgi.gateways_cnt >= MAX_GATEWAYS) {
uwsgi_log("you can register max %d gateways\n", MAX_GATEWAYS);
return NULL;
}
for(i=0;i<uwsgi.gateways_cnt;i++) {
if (!strcmp(name, uwsgi.gateways[i].name)) {
num++;
}
}
gw_pid = fork();
if (gw_pid < 0) {
uwsgi_error("fork()");
return NULL;
}
if (!uwsgi.master_process) {
if (gw_pid > 0) {
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0,0,0)) {
uwsgi_error("prctl()");
}
#endif
loop();
// never here !!! (i hope)
exit(1);
}
ug = &uwsgi.gateways[uwsgi.gateways_cnt];
ug->pid = orig_pid;
}
else {
if (gw_pid == 0) {
if (uwsgi.master_as_root) uwsgi_as_root();
loop();
// never here !!! (i hope)
exit(1);
}
ug = &uwsgi.gateways[uwsgi.gateways_cnt];
ug->pid = gw_pid;
}
ug->name = name;
ug->loop = loop;
ug->num = num;
uwsgi_log( "spawned uWSGI %s %d (pid: %d)\n", ug->name, ug->num, (int) ug->pid);
uwsgi.gateways_cnt++;
return ug;
}
void gateway_respawn(int id) {
pid_t gw_pid;
struct uwsgi_gateway *ug = &uwsgi.gateways[id];
gw_pid = fork();
if (gw_pid < 0) {
uwsgi_error("fork()");
return;
}
if (gw_pid == 0) {
if (uwsgi.master_as_root) uwsgi_as_root();
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0,0,0)) {
uwsgi_error("prctl()");
}
#endif
ug->loop();
// never here !!! (i hope)
exit(1);
}
ug->pid = gw_pid;
uwsgi_log( "respawned uWSGI %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
}
+9
View File
@@ -0,0 +1,9 @@
// http:3:GET / HTTP/1.1:192.168.173.10:80,192.168.173.11:80,192.168.173.12:80,192.168.173.13:80
/*
write(arg1);
wait_for_fd()
get_data() == 200
*/
View File
View File
View File
View File
+1
View File
@@ -0,0 +1 @@
// uwsgi:3::192.168.173.1:3031,192.168.173.2:3031,192.168.173.3:3031,192.168.173.4:3031
+7 -14
View File
@@ -6,20 +6,18 @@ import rrdtool
s_freq = 10
# this is a cron emulator done with the Spooler :)
def rrdtool_updater(env):
uwsgi.set_spooler_frequency(s_freq)
rrdtool.update('../test.rrd', str(int(time.time()))+':'+str(uwsgi.total_requests()))
uwsgi.send_to_spooler({})
# this task will be executed every s_freq seconds
def rrdtool_updater(sig, sec):
rrdtool.update('test.rrd', str(int(time.time()))+':'+str(uwsgi.total_requests()))
uwsgi.spooler = rrdtool_updater
uwsgi.register_timer(0, s_freq, uwsgi.KIND_WORKER, rrdtool_updater)
def hello_world(env, start_response):
start_response('200 Ok', [('Content-type', 'text/plain')])
yield 'Hello world !'
return 'Hello world !'
def graph(env, start_response):
@@ -27,12 +25,7 @@ def graph(env, start_response):
now = int(time.time())
graph_range = (3600*24)
rrdtool.graph('uwsgi_graph.png', '--start', str(now - graph_range), '--end', str(now), 'DEF:urequests=test.rrd:requests:AVERAGE', 'LINE2:urequests#00FF00')
fd = open('uwsgi_graph.png', 'r')
# send file to browser
return env['wsgi.file_wrapper'](fd, 4096)
# start the simil-cron
uwsgi.send_to_spooler({})
# send file to client
uwsgi.sendfile('uwsgi_graph.png')
uwsgi.applications = {'/': hello_world, '/graph':graph}
+141
View File
@@ -0,0 +1,141 @@
#ifdef UWSGI_INI
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
/*
ini file must be read ALL into memory.
This memory must not be freed for all the server lifecycle
*/
void ini_rstrip(char *line) {
off_t i;
for(i = strlen(line)-1;i>=0; i--) {
if (line[i] == ' ' || line[i] == '\t') {
line[i] = 0;
continue;
}
break;
}
}
char *ini_lstrip(char *line) {
off_t i;
char *ptr = line;
for(i=0;i< (int) strlen(line);i++) {
if (line[i] == ' ' || line[i] == '\t') {
ptr++;
continue;
}
break;
}
return ptr;
}
char *ini_get_key(char *key) {
off_t i;
char *ptr = key;
for(i=0;i< (int) strlen(key);i++) {
ptr++;
if (key[i] == '=') {
key[i] = 0;
return ptr;
}
}
return ptr;
}
char *ini_get_line(char *ini, off_t size) {
off_t i;
char *ptr = ini;
for(i=0;i<size;i++) {
ptr++;
if (ini[i] == '\n') {
ini[i] = 0;
return ptr;
}
}
return NULL;
}
void uwsgi_ini_config(char *file, char *magic_table[]) {
int len = 0;
char *ini;
char *ini_line;
char *section = "";
char *key;
char *val;
int lines = 1;
char *section_asked = "uwsgi";
char *colon;
colon = uwsgi_get_last_char(file, ':');
if (colon) {
colon[0] = 0;
if (colon[1] != 0) {
section_asked = colon+1;
}
}
uwsgi_log("[uWSGI] getting INI configuration from %s\n", file);
ini = uwsgi_open_and_read(file, &len, 1, magic_table);
while(len) {
ini_line = ini_get_line(ini, len);
if (ini_line == NULL) {
break;
}
lines++;
// skip empty line
key = ini_lstrip(ini);
ini_rstrip(key);
if (key[0] != 0) {
if (key[0] == '[') {
section = key+1;
section[strlen(section)-1] = 0;
}
else if (key[0] == ';' || key[0] == '#') {
// this is a comment
}
else {
// val is always valid, but (obviously) can be ignored
val = ini_get_key(key);
if (!strcmp(section, section_asked)) {
ini_rstrip(key);
val = ini_lstrip(val);
ini_rstrip(val);
add_exported_option((char *)key, val, 0);
}
}
}
len -= (ini_line - ini);
ini += (ini_line - ini);
}
}
#endif
+393
View File
@@ -0,0 +1,393 @@
#ifdef UWSGI_LDAP
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#include <ldap.h>
#ifndef LDAP_OPT_SUCCESS
#define LDAP_OPT_SUCCESS LDAP_SUCCESS
#endif
#ifndef ldap_unbind_ext_s
#define ldap_unbind_ext_s ldap_unbind_ext
#endif
void ldap2uwsgi(char *ldapname, char *uwsginame) {
char *ptr = uwsginame;
int i;
for(i=0;i< (int) strlen(ldapname);i++) {
if (isupper( (int)ldapname[i])) {
*ptr++ = '-';
*ptr++ = tolower( (int) ldapname[i]);
}
else {
*ptr++ = ldapname[i];
}
}
*ptr++= 0;
}
int calc_ldap_name(char *name) {
int i;
int counter = 0;
for(i=0;i< (int)strlen(name);i++) {
if (isupper( (int) name[i])) {
counter++;
}
}
return strlen(name) + counter;
}
struct uwsgi_ldap_entry {
int num;
char names[1024];
int has_arg;
};
void uwsgi_name_to_ldap(char *src, char *dst) {
int i;
char *ptr = dst;
memset(dst, 0, 1024);
strcat(dst, " 'uWSGI");
ptr+= 7;
for(i=0;i< (int)strlen(src);i++) {
if (src[i] == '-') {
i++;
*ptr++= toupper( (int) src[i]);
}
else {
*ptr++= src[i];
}
}
strcat(dst, "'");
}
struct uwsgi_ldap_entry *get_ldap_by_num(struct uwsgi_ldap_entry *root, int num, int count) {
int i;
struct uwsgi_ldap_entry *ule;
for(i=0;i<count;i++) {
ule = &root[i];
if (ule->num == num) {
return ule;
}
}
return NULL;
}
struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *name, int count) {
int i;
struct uwsgi_ldap_entry *ule;
for(i=0;i<count;i++) {
ule = &root[i];
if (uwsgi_list_has_str(ule->names, name+1)) {
return ule;
}
}
return NULL;
}
struct uwsgi_ldap_entry *get_ldap_names(int *count) {
struct option *aopt, *lopt;
struct uwsgi_ldap_entry *ule, *entry;
char ldap_name[1024];
static int counter = 30000000;
*count = 0;
lopt = uwsgi.long_options;
ule = uwsgi_malloc(sizeof(struct uwsgi_ldap_entry)*count_options(lopt));
while( (aopt = lopt) ) {
if (!aopt->name)
break;
uwsgi_name_to_ldap((char *)aopt->name, ldap_name);
entry = search_ldap_cache(ule, ldap_name, *count);
if (entry) goto next;
if (aopt->flag) {
entry = &ule[*count] ;
entry->num = counter;
strcpy(entry->names, ldap_name);
counter++;
*count = *count+1;
}
else {
entry = get_ldap_by_num(ule, aopt->val, *count);
if (entry) {
strcat(entry->names, ldap_name);
}
else {
entry = &ule[*count] ;
entry->num = aopt->val;
strcpy(entry->names, ldap_name);
*count = *count+1;
}
}
entry->has_arg = aopt->has_arg;
next:
lopt++;
}
return ule;
}
void uwsgi_ldap_schema_dump_ldif() {
int i;
int items;
uwsgi_log("\n");
uwsgi_log("dn: cn=uwsgi,cn=schema,cn=config\n");
uwsgi_log("objectClass: olcSchemaConfig\n");
uwsgi_log("cn: uwsgi\n");
struct uwsgi_ldap_entry *entry, *ule = get_ldap_names(&items);
for(i=0;i<items;i++) {
entry = &ule[i];
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
if (entry->has_arg) {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
}
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
uwsgi_log("olcObjectClasses: ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
for(i=0;i<items;i++) {
entry = &ule[i];
char *list2 = uwsgi_concat2(entry->names+1, "");
char *p = strtok(list2, " ");
while (p != NULL) {
uwsgi_log("%.*s $ ", strlen(p)-2, p+1);
p = strtok(NULL, " ");
}
free(list2);
}
uwsgi_log("uWSGInull ))\n");
uwsgi_log("\n");
exit(0);
}
void uwsgi_ldap_schema_dump() {
int i;
int items;
struct uwsgi_ldap_entry *entry, *ule = get_ldap_names(&items);
for(i=0;i<items;i++) {
entry = &ule[i];
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
if (entry->has_arg) {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
}
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
uwsgi_log("objectclass ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
for(i=0;i<items;i++) {
entry = &ule[i];
char *list2 = uwsgi_concat2(entry->names+1, "");
char *p = strtok(list2, " ");
while (p != NULL) {
uwsgi_log("%.*s $ ", strlen(p)-2, p+1);
p = strtok(NULL, " ");
}
free(list2);
}
uwsgi_log("uWSGInull ))\n");
exit(0);
}
void uwsgi_ldap_config() {
LDAP *ldp;
LDAPMessage *results, *entry;
BerElement *ber;
struct berval **bervalues;
char *attr;
char *uwsgi_attr;
char *url = "ldap:///";
char *url_slash;
int desired_version = LDAP_VERSION3;
int ret;
LDAPURLDesc *ldap_url;
if (uwsgi.ldap) {
url = uwsgi.ldap;
}
if (!ldap_is_ldap_url(url)) {
uwsgi_log("invalid LDAP url.\n");
exit(1);
}
if (ldap_url_parse(url, &ldap_url) != LDAP_SUCCESS) {
uwsgi_log("unable to parse LDAP url.\n");
exit(1);
}
uwsgi_log("[uWSGI] getting LDAP configuration from %s\n", url);
url_slash = strchr(url, '/');
url_slash = strchr(url_slash + 1, '/');
url_slash = strchr(url_slash + 1, '/');
if (url_slash) {
url_slash[0] = 0;
}
#ifdef UWSGI_DEBUG
uwsgi_debug("LDAP URL: %s\n", url);
uwsgi_debug("LDAP BASE DN: %s\n", ldap_url->lud_dn);
#endif
#if LDAP_API_VERSION >= 3000
if ( (ret = ldap_initialize( &ldp, url)) != LDAP_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
#else
if ( (ldp = ldap_init( ldap_url->lud_host, ldap_url->lud_port)) == NULL) {
uwsgi_error("ldap_init()");
exit(1);
}
#endif
if ( (ret = ldap_set_option(ldp, LDAP_OPT_PROTOCOL_VERSION, &desired_version)) != LDAP_OPT_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
if ( (ret = ldap_search_ext_s(ldp, ldap_url->lud_dn, ldap_url->lud_scope, ldap_url->lud_filter, NULL, 0, NULL, NULL, NULL, 1, &results)) != LDAP_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
#ifdef UWSGI_DEBUG
uwsgi_debug("LDAP connection initialized %p\n", ldp);
#endif
free(ldap_url);
if (ldap_count_entries(ldp, results) < 1) {
uwsgi_log("no LDAP entry found\n");
exit(1);
}
entry = ldap_first_entry(ldp, results);
int found = 0;
for( attr = ldap_first_attribute(ldp, entry, &ber); attr != NULL; attr = ldap_next_attribute(ldp, entry, ber)) {
if (!strncmp(attr,"uWSGI",5)) {
found = 1;
uwsgi_attr = malloc( calc_ldap_name(attr) + 1 );
if (!uwsgi_attr) {
uwsgi_error("malloc()");
exit(1);
}
ldap2uwsgi(attr+5, uwsgi_attr);
#ifdef UWSGI_DEBUG
uwsgi_debug("LDAP attribute: %s = --%s\n", attr, uwsgi_attr);
#endif
bervalues = ldap_get_values_len(ldp, entry, attr);
if (bervalues) {
// do not free uwsgi_attr/uwsgi_val;
char *uwsgi_val = malloc( bervalues[0]->bv_len + 1 );
if (!uwsgi_val) {
uwsgi_error("malloc()");
exit(1);
}
memcpy(uwsgi_val, bervalues[0]->bv_val, bervalues[0]->bv_len);
uwsgi_val[bervalues[0]->bv_len] = 0;
add_exported_option((char*) uwsgi_attr, uwsgi_val, 0);
free(bervalues);
}
else {
free(uwsgi_attr);
}
}
free(attr);
}
if (!found) {
uwsgi_log("no uWSGI LDAP entry found\n");
exit(1);
}
free(ber);
free(results);
ldap_unbind_ext_s(ldp, NULL, NULL);
}
#endif
+799
View File
@@ -0,0 +1,799 @@
#include "../uwsgi.h"
#define AMQP_CONNECTION_HEADER "AMQP\0\0\x09\x01"
#ifdef __BIG_ENDIAN__
#define ntohll(x) x
#else
#define ntohll(x) ( ( (uint64_t)(ntohl( (uint32_t)((x << 32) >> 32) )) << 32) | ntohl( ((uint32_t)(x >> 32)) ) )
#endif
#define htonll(x) ntohll(x)
#define amqp_send(a, b, c) if (send(a, b, c, 0) < 0) { uwsgi_error("send()"); return -1; }
struct amqp_frame_header {
char type;
uint16_t channel;
uint32_t size;
} __attribute__((__packed__));
struct amqp_frame_method {
uint16_t class_id;
uint16_t method_id;
} __attribute__((__packed__));
static char *amqp_simple_get_frame(int, struct amqp_frame_header *);
static char *amqp_get_method(int, uint16_t, uint16_t, uint32_t *);
/*
static char *amqp_get_longstr(char *ptr, char *watermark) {
uint32_t longstr_size;
if (ptr+4 > watermark) return NULL;
memcpy(&longstr_size, ptr, 4);
longstr_size = ntohl(longstr_size);
if (ptr+4+longstr_size > watermark) return NULL;
return ptr+4+longstr_size;
}
*/
static char *amqp_get_str(char *ptr, char *watermark) {
uint8_t str_size;
// over engeneering...
if (ptr+1 > watermark) return NULL;
str_size = *ptr;
if (ptr+1+str_size > watermark) return NULL;
return ptr+1+str_size;
}
/*
static char *amqp_get_table(char *ptr, char *watermark) {
uint32_t table_size;
if (ptr+4 > watermark) return NULL;
memcpy(&table_size, ptr, 4);
table_size = ntohl(table_size);
if (ptr+4+table_size > watermark) return NULL;
return ptr+4+table_size;
}
*/
static char *amqp_get_short(char *ptr, char *watermark, uint16_t *sv) {
uint16_t tmp_short;
if (ptr+2 > watermark) return NULL;
memcpy(&tmp_short, ptr, 2);
*sv = ntohs(tmp_short);
return ptr+2;
}
static char *amqp_get_long(char *ptr, char *watermark, uint32_t *lv) {
uint32_t tmp_long;
if (ptr+4 > watermark) return NULL;
memcpy(&tmp_long, ptr, 4);
*lv = ntohl(tmp_long);
return ptr+4;
}
static char *amqp_get_longlong(char *ptr, char *watermark, uint64_t *llv) {
uint64_t tmp_longlong;
if (ptr+8 > watermark) return NULL;
memcpy(&tmp_longlong, ptr, 8);
*llv = ntohll(tmp_longlong);
return ptr+8;
}
static int amqp_send_ack(int fd, uint64_t delivery_tag) {
uint32_t size = 4 + 8 + 1;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\1", 3);
// send size
amqp_send(fd, &size, 4);
// send class 60 method 80
amqp_send(fd, "\x00\x3C\x00\x50", 4);
// set delivery_tag
delivery_tag = htonll(delivery_tag);
amqp_send(fd, &delivery_tag, 8);
// empty bits
amqp_send(fd, "\0", 1);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
char *uwsgi_amqp_consume(int fd, uint64_t *msgsize, char **routing_key) {
uint32_t size;
struct amqp_frame_header fh;
uint64_t delivery_tag;
uint64_t current_size = 0;
char *ptr;
char *watermark;
uint16_t sv;
char *frame = amqp_get_method(fd, 60, 60, &size);
if (!frame) return NULL;
ptr = frame+4;
watermark = frame+size;
// consumer_tag
ptr = amqp_get_str(ptr, watermark); if (!ptr) goto clear;
// delivery_tag (needed for ack)
ptr = amqp_get_longlong(ptr, watermark, &delivery_tag); if (!ptr) goto clear;
// redelivered
if (ptr+1 > watermark) goto clear;
ptr++;
// exchange
ptr = amqp_get_str(ptr, watermark); if (!ptr) goto clear;
// routing_key
if (ptr+1 > watermark) goto clear;
uint8_t rk_size = (uint8_t) *ptr;
ptr++;
if (ptr+rk_size > watermark) goto clear;
if (rk_size > 0) {
char *rkey = uwsgi_concat2n(ptr, rk_size, "", 0);
ptr+=rk_size;
*routing_key = rkey;
}
else {
*routing_key = NULL;
}
char *header = amqp_simple_get_frame(fd, &fh);
if (!header) goto clear;
if (fh.type != 2) goto clear2;
ptr = header;
watermark = ptr+fh.size;
// header class_id
ptr = amqp_get_short(ptr, watermark, &sv); if (!ptr) goto clear2;
// header weight
ptr = amqp_get_short(ptr, watermark, &sv); if (!ptr) goto clear2;
// message size;
ptr = amqp_get_longlong(ptr, watermark, msgsize); if (!ptr) goto clear2;
free(frame);
free(header);
char *fullbody = uwsgi_malloc(*msgsize);
char *message;
while(current_size < *msgsize) {
message = amqp_simple_get_frame(fd, &fh);
if (!message) goto clear;
if (fh.type != 3) {
free(message);
goto clear3;
}
if (fh.size+current_size > *msgsize) {
free(message);
goto clear3;
}
memcpy(fullbody+current_size, message, fh.size);
current_size+=fh.size;
free(message);
}
if (amqp_send_ack(fd, delivery_tag) < 0) {
goto clear3;
}
return fullbody;
clear3:
free(fullbody);
return NULL;
clear2:
free(header);
clear:
free(frame);
return NULL;
}
static int amqp_send_exchange_declare( int fd, char *exchange, char *exchange_type) {
uint32_t size = 4 + 2 + (1 +strlen(exchange)) + (1 +strlen(exchange_type)) + 1 + 4;
uint8_t shortsize = strlen(exchange) ;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\1", 3);
// send size
amqp_send(fd, &size, 4);
// send class 40 method 10
amqp_send(fd, "\x00\x28\x00\x0A", 4);
// send empty reserved
amqp_send(fd, "\0\0", 2);
// set exchange name
amqp_send(fd, &shortsize, 1);
amqp_send(fd, exchange, shortsize);
// set exchange type
shortsize = strlen(exchange_type);
amqp_send(fd, &shortsize, 1);
amqp_send(fd, exchange_type, shortsize);
// empty bits
amqp_send(fd, "\0", 1);
// empty table
amqp_send(fd, "\0\0\0\0", 4);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
static int amqp_send_queue_bind( int fd, char *queue, char *exchange) {
uint32_t size = 4 + 2 + (1 +strlen(queue)) + (1 +strlen(exchange)) + 1 + 1 + 4;
uint8_t shortsize = strlen(queue) ;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\1", 3);
// send size
amqp_send(fd, &size, 4);
// send class 50 method 20
amqp_send(fd, "\x00\x32\x00\x14", 4);
// send empty reserved
amqp_send(fd, "\0\0", 2);
// set queue name
amqp_send(fd, &shortsize, 1);
amqp_send(fd, queue, shortsize);
// set exchange name
shortsize = strlen(exchange);
amqp_send(fd, &shortsize, 1);
amqp_send(fd, exchange, shortsize);
// set empty routing-key
amqp_send(fd, "\0", 1);
// empty bits
amqp_send(fd, "\0", 1);
// empty table
amqp_send(fd, "\0\0\0\0", 4);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
static int amqp_send_queue_consume( int fd, char *queue) {
uint32_t size = 4 + 2 + (1 +strlen(queue)) + 1 + 1 + 4;
uint8_t shortsize = strlen(queue) ;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\1", 3);
// send size
amqp_send(fd, &size, 4);
// send class 60 method 20
amqp_send(fd, "\x00\x3C\x00\x14", 4);
// send empty reserved
amqp_send(fd, "\0\0", 2);
// set queue name
amqp_send(fd, &shortsize, 1);
amqp_send(fd, queue, shortsize);
// set tag name
amqp_send(fd, "\0", 1);
// empty bits
amqp_send(fd, "\0", 1);
// empty table
amqp_send(fd, "\0\0\0\0", 4);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
static int amqp_wait_connection_start(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 10, 10, &size);
if (frame) {
free(frame);
return 0;
}
return -1;
}
static int amqp_wait_exchange_declare_ok(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 40, 11, &size);
if (frame) {
free(frame);
return 0;
}
return -1;
}
static int amqp_wait_basic_consume_ok(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 60, 21, &size);
if (frame) {
free(frame);
return 0;
}
return -1;
}
static int amqp_wait_channel_open_ok(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 20, 11, &size);
if (frame) {
free(frame);
return 0;
}
return -1;
}
static int amqp_wait_queue_bind_ok(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 50, 21, &size);
if (frame) {
free(frame);
return 0;
}
return -1;
}
static char *amqp_wait_queue_declare_ok(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 50, 11, &size);
char *queue = NULL;
char *ptr;
char *watermark;
if (frame) {
ptr = frame+4;
watermark = frame+size;
ptr = amqp_get_str(ptr, watermark); if (!ptr) { free(frame); return NULL; }
queue = uwsgi_concat2n(frame+5, *(frame+4), "", 0);
free(frame);
return queue;
}
return NULL;
}
static int amqp_wait_connection_open_ok(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 10, 41, &size);
if (frame) {
free(frame);
return 0;
}
return -1;
}
static int amqp_wait_connection_tune(int fd) {
uint32_t size;
char *frame = amqp_get_method(fd, 10, 30, &size);
uint16_t sv;
uint32_t lv;
char *watermark ;
char *ptr;
if (frame) {
ptr = frame+4;
watermark = frame+size;
ptr = amqp_get_short(ptr, watermark, &sv); if (!ptr) { free(frame); return -1; }
uwsgi_log("AMQP max channels: %d\n", sv);
ptr = amqp_get_long(ptr, watermark, &lv); if (!ptr) { free(frame); return -1; }
uwsgi_log("AMQP max frame size: %d\n", lv);
ptr = amqp_get_short(ptr, watermark, &sv); if (!ptr) { free(frame); return -1; }
uwsgi_log("AMQP heartbeath: %d\n", sv);
free(frame);
return 0;
}
return -1;
}
static char *amqp_simple_get_frame(int fd, struct amqp_frame_header *fh) {
char *ptr = (char *) fh;
size_t len = 0, rlen;
while(len < 7) {
rlen = recv(fd, ptr, 7-len, 0);
if (rlen <= 0) {
uwsgi_error("recv()");
return NULL;
}
len += rlen;
ptr += rlen;
}
fh->channel = ntohs(fh->channel);
fh->size = ntohl(fh->size);
len = 0;
char *frame = malloc(fh->size+1);
ptr = frame;
while(len < fh->size+1) {
rlen = recv(fd, ptr, (fh->size+1)-len, 0);
if (rlen <= 0) {
uwsgi_error("recv()");
return NULL;
}
len += rlen;
ptr += rlen;
}
return frame;
}
static char *amqp_get_method(int fd, uint16_t class_id, uint16_t method_id, uint32_t *size) {
struct amqp_frame_header fh;
struct amqp_frame_method *fm;
char *frame = amqp_simple_get_frame(fd, &fh);
if (!frame) return NULL;
if (fh.type != 1) goto clear;
fm = (struct amqp_frame_method *) frame;
fm->class_id = ntohs(fm->class_id);
fm->method_id = ntohs(fm->method_id);
if (fm->class_id != class_id) goto clear;
if (fm->method_id != method_id) goto clear;
*size = fh.size;
return frame;
clear:
free(frame);
return NULL;
}
static int amqp_send_channel_open(int fd, uint16_t id) {
uint32_t size = 4 + 1;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\1", 3);
// send size
amqp_send(fd, &size, 4);
// send class 20 method 10
amqp_send(fd, "\x00\x14\x00\x0A", 4);
amqp_send(fd, "\0", 1);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
int amqp_send_connection_open(int fd, char *vhost) {
uint8_t shortsize = strlen(vhost);
uint32_t size = 4 + 1 +strlen(vhost) + 2;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\0", 3);
// send size
amqp_send(fd, &size, 4);
// send class 10 method 28
amqp_send(fd, "\x00\x0A\x00\x28", 4);
amqp_send(fd, &shortsize, 1);
amqp_send(fd, vhost, strlen(vhost));
shortsize = 0;
amqp_send(fd, &shortsize, 1);
amqp_send(fd, &shortsize, 1);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
int amqp_send_connection_tune_ok(int fd, uint16_t max_chan, uint32_t max_frame_size, uint16_t heartbeat) {
uint32_t size = 4 + 2 + 4 + 2;
size = htonl(size);
max_chan = htons(max_chan);
max_frame_size = htonl(max_frame_size);
heartbeat = htons(heartbeat);
// send type and channel
amqp_send(fd, "\1\0\0", 3);
// send size
amqp_send(fd, &size, 4);
// send class 10 method 15
amqp_send(fd, "\x00\x0A\x00\x1F", 4);
amqp_send(fd, &max_chan, 2);
amqp_send(fd, &max_frame_size, 4);
amqp_send(fd, &heartbeat, 2);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
static int amqp_send_queue_declare(int fd, char *queue) {
uint32_t size = 4 + 2 + (1 +strlen(queue)) + 1 + 4;
uint8_t shortsize = strlen(queue) ;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\1", 3);
// send size
amqp_send(fd, &size, 4);
// send class 50 method 10
amqp_send(fd, "\x00\x32\x00\x0A", 4);
// send empty reserved
amqp_send(fd, "\0\0", 2);
// set queue name
amqp_send(fd, &shortsize, 1);
amqp_send(fd, queue, shortsize);
// empty bits
amqp_send(fd, "\0", 1);
// empty table
amqp_send(fd, "\0\0\0\0", 4);
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
static char *amqp_get_queue(int fd, char *queue) {
if (amqp_send_queue_declare(fd, queue) < 0) {
return NULL;
}
return amqp_wait_queue_declare_ok(fd);
}
static int amqp_send_connection_start_ok(int fd, char *mech, char *sasl_response, int sasl_response_size, char *locale) {
uint32_t size = 4 + 4 + (1 +strlen(mech)) + (4 + sasl_response_size) + (1 + strlen(locale));
uint8_t shortsize ;
size = htonl(size);
// send type and channel
amqp_send(fd, "\1\0\0", 3);
// send size
amqp_send(fd, &size, 4);
// send class 10 method 11
amqp_send(fd, "\x00\x0A\x00\x0B", 4);
// send empty client properties
amqp_send(fd, "\0\0\0\0", 4);
// send mechanism short string
shortsize = strlen(mech);
amqp_send(fd, &shortsize, 1);
amqp_send(fd, mech, strlen(mech));
// send sasl response
size = htonl(sasl_response_size);
amqp_send(fd, &size, 4);
amqp_send(fd, sasl_response, sasl_response_size);
// send locale
shortsize = strlen(locale);
amqp_send(fd, &shortsize, 1);
amqp_send(fd, locale, strlen(locale));
// send frame-end
amqp_send(fd, "\xCE", 1);
return 0;
}
int uwsgi_amqp_consume_queue(int fd, char *vhost, char *queue, char *exchange, char *exchange_type) {
if (send(fd, AMQP_CONNECTION_HEADER, 8, 0) < 0) {
uwsgi_error("send()");
return -1;
}
if (amqp_wait_connection_start(fd) < 0) {
uwsgi_log("AMQP error waiting for Connection.start\n");
return -1;
}
uwsgi_log("sending Connection.start-ok\n");
if (amqp_send_connection_start_ok(fd, "PLAIN", "\0guest\0guest", 12, "en_US") < 0) {
uwsgi_log("AMQP error sending Connection.start-ok\n");
return -1;
}
if (amqp_wait_connection_tune(fd) < 0) {
uwsgi_log("AMQP error waiting for Connection.tune\n");
return -1;
}
uwsgi_log("sending Connection.tune-ok\n");
if (amqp_send_connection_tune_ok(fd, 0, 0xffff, 0) < 0) {
uwsgi_log("AMQP error sending Connection.tune-ok\n");
return -1;
}
uwsgi_log("sending Connection.open\n");
if (amqp_send_connection_open(fd, vhost) < 0) {
uwsgi_log("AMQP error sending Connection.open\n");
return -1;
}
if (amqp_wait_connection_open_ok(fd) < 0) {
uwsgi_log("AMQP error waiting for Connection.open-ok\n");
return -1;
}
uwsgi_log("sending Channel.open\n");
if (amqp_send_channel_open(fd, 1) < 0) {
uwsgi_log("AMQP error sending Channel.open\n");
return -1;
}
if (amqp_wait_channel_open_ok(fd) < 0) {
uwsgi_log("AMQP error waiting for Channel.open-ok\n");
return -1;
}
queue = amqp_get_queue(fd, queue);
if (!queue) {
uwsgi_log("AMQP error sending Queue.declare\n");
return -1;
}
if (exchange) {
if (amqp_send_exchange_declare(fd, exchange, exchange_type) < 0) {
uwsgi_log("AMQP error sending Exchange.declare\n");
free(queue);
return -1;
}
if (amqp_wait_exchange_declare_ok(fd) < 0) {
uwsgi_log("AMQP error waiting for Exchange.declare-ok\n");
free(queue);
return -1;
}
if (amqp_send_queue_bind(fd, queue, exchange) < 0) {
uwsgi_log("AMQP error sending Queue.bind\n");
free(queue);
return -1;
}
if (amqp_wait_queue_bind_ok(fd) < 0) {
uwsgi_log("AMQP error waiting for Queue.bind-ok\n");
free(queue);
return -1;
}
}
if (amqp_send_queue_consume(fd, queue) < 0) {
uwsgi_log("AMQP error sending Basic.consume\n");
free(queue);
return -1;
}
if (amqp_wait_basic_consume_ok(fd) < 0) {
uwsgi_log("AMQP error waiting for Basic.consume-ok\n");
free(queue);
return -1;
}
free(queue);
return 0;
}
+379
View File
@@ -0,0 +1,379 @@
#include "../uwsgi.h"
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <net/if.h>
#define NLMSG_TAIL(nmsg) \
((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
#ifndef VETH_INFO_PEER
# define VETH_INFO_PEER 1
#endif
struct uwsgi_nl_req {
struct nlmsghdr nlmsg;
struct ifinfomsg ifinfomsg;
};
struct uwsgi_nl_ipreq {
struct nlmsghdr nlmsg;
struct ifaddrmsg ifaddrmsg;
};
struct uwsgi_nl_rtreq {
struct nlmsghdr nlmsg;
struct rtmsg rtmsg;
};
int uwsgi_nl_send(struct nlmsghdr *);
struct nlmsghdr *uwsgi_netlink_alloc() {
size_t len = NLMSG_ALIGN(8192) + NLMSG_ALIGN(sizeof(struct nlmsghdr *));
struct nlmsghdr *nlmsg = (struct nlmsghdr *) uwsgi_malloc(len);
memset(nlmsg, 0, len);
struct uwsgi_nl_req *unr = (struct uwsgi_nl_req *)nlmsg;
unr->ifinfomsg.ifi_family = AF_UNSPEC;
nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
nlmsg->nlmsg_type = RTM_NEWLINK;
nlmsg->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
return nlmsg;
}
struct nlmsghdr *uwsgi_netlink_ip_alloc() {
size_t len = NLMSG_ALIGN(8192) + NLMSG_ALIGN(sizeof(struct nlmsghdr *));
struct nlmsghdr *nlmsg = (struct nlmsghdr *) uwsgi_malloc(len);
memset(nlmsg, 0, len);
struct uwsgi_nl_ipreq *uni = (struct uwsgi_nl_ipreq *)nlmsg;
uni->ifaddrmsg.ifa_family = AF_INET;
uni->ifaddrmsg.ifa_scope = 0;
nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
nlmsg->nlmsg_type = RTM_NEWADDR;
nlmsg->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK|NLM_F_CREATE|NLM_F_EXCL;
return nlmsg;
}
struct nlmsghdr *uwsgi_netlink_rt_alloc() {
size_t len = NLMSG_ALIGN(8192) + NLMSG_ALIGN(sizeof(struct nlmsghdr *));
struct nlmsghdr *nlmsg = (struct nlmsghdr *) uwsgi_malloc(len);
memset(nlmsg, 0, len);
struct uwsgi_nl_rtreq *unr = (struct uwsgi_nl_rtreq *)nlmsg;
unr->rtmsg.rtm_family = AF_INET;
unr->rtmsg.rtm_table = RT_TABLE_MAIN;
unr->rtmsg.rtm_protocol = RTPROT_STATIC;
unr->rtmsg.rtm_scope = RT_SCOPE_UNIVERSE;
unr->rtmsg.rtm_type = RTN_UNICAST;
nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
nlmsg->nlmsg_type = RTM_NEWROUTE;
nlmsg->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK|NLM_F_CREATE|NLM_F_EXCL;
return nlmsg;
}
int uwsgi_netlink_rt(char *src, char *dst, int dst_prefix, char *gw) {
struct nlmsghdr *nlmsg = uwsgi_netlink_rt_alloc();
struct rtattr *rta;
struct in_addr ia;
struct in_addr oa;
struct in_addr ga;
struct uwsgi_nl_rtreq *unr = (struct uwsgi_nl_rtreq *)nlmsg;
if (inet_pton(AF_INET, src, &ia) <= 0) {
uwsgi_error("inet_pton()");
free(nlmsg);
return -1;
}
if (inet_pton(AF_INET, dst, &oa) <= 0) {
uwsgi_error("inet_pton()");
free(nlmsg);
return -1;
}
if (inet_pton(AF_INET, gw, &ga) <= 0) {
uwsgi_error("inet_pton()");
free(nlmsg);
return -1;
}
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = RTA_PREFSRC;
rta->rta_len = RTA_LENGTH(4);
memcpy(RTA_DATA(rta), &ia.s_addr, 4);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = RTA_DST;
rta->rta_len = RTA_LENGTH(4);
memcpy(RTA_DATA(rta), &oa.s_addr, 4);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = RTA_GATEWAY;
rta->rta_len = RTA_LENGTH(4);
memcpy(RTA_DATA(rta), &ga.s_addr, 4);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
unr->rtmsg.rtm_src_len = 0;
unr->rtmsg.rtm_dst_len = dst_prefix;
return uwsgi_nl_send(nlmsg);
}
int uwsgi_netlink_gw(char *iface, char *ip) {
struct nlmsghdr *nlmsg = uwsgi_netlink_rt_alloc();
struct rtattr *rta;
struct in_addr ia;
uint32_t zero = 0;
int index = if_nametoindex(iface);
if (!index) return -1;
if (inet_pton(AF_INET, ip, &ia) <= 0) {
uwsgi_error("inet_pton()");
free(nlmsg);
return -1;
}
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = RTA_GATEWAY;
rta->rta_len = RTA_LENGTH(4);
memcpy(RTA_DATA(rta), &ia.s_addr, 4);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = RTA_DST;
rta->rta_len = RTA_LENGTH(4);
memcpy(RTA_DATA(rta), &zero, 4);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = RTA_OIF;
rta->rta_len = RTA_LENGTH(sizeof(int));
memcpy(RTA_DATA(rta), &index, sizeof(int));
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
return uwsgi_nl_send(nlmsg);
}
int uwsgi_netlink_ip(char *iface, char *ip, int prefix) {
struct nlmsghdr *nlmsg = uwsgi_netlink_ip_alloc();
struct uwsgi_nl_ipreq *uni = (struct uwsgi_nl_ipreq *)nlmsg;
struct rtattr *rta;
struct in_addr ia;
int index = if_nametoindex(iface);
if (!index) return -1;
uni->ifaddrmsg.ifa_index = index;
uni->ifaddrmsg.ifa_prefixlen = prefix;
if (inet_pton(AF_INET, ip, &ia) <= 0) {
uwsgi_error("inet_pton()");
free(nlmsg);
return -1;
}
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = IFA_LOCAL;
rta->rta_len = RTA_LENGTH(sizeof(struct in_addr));
memcpy(RTA_DATA(rta), &ia, sizeof(struct in_addr));
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = IFA_ADDRESS;
rta->rta_len = RTA_LENGTH(sizeof(struct in_addr));
memcpy(RTA_DATA(rta), &ia, sizeof(struct in_addr));
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
return uwsgi_nl_send(nlmsg);
}
int uwsgi_netlink_veth_attach(char *veth1, pid_t pid) {
struct nlmsghdr *nlmsg = uwsgi_netlink_alloc();
struct uwsgi_nl_req *unr = (struct uwsgi_nl_req *)nlmsg;
struct rtattr *rta;
int index = if_nametoindex(veth1);
if (!index) return -1;
unr->ifinfomsg.ifi_index = index;
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = IFLA_NET_NS_PID;
rta->rta_len = RTA_LENGTH(sizeof(pid_t));
memcpy(RTA_DATA(rta), &pid, sizeof(pid_t));
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
return uwsgi_nl_send(nlmsg);
}
int uwsgi_netlink_ifup(char *iface) {
struct nlmsghdr *nlmsg = uwsgi_netlink_alloc();
struct uwsgi_nl_req *unr = (struct uwsgi_nl_req *)nlmsg;
int index = if_nametoindex(iface);
if (!index) return -1;
unr->ifinfomsg.ifi_index = index;
unr->ifinfomsg.ifi_change |= IFF_UP;
unr->ifinfomsg.ifi_flags |= IFF_UP;
return uwsgi_nl_send(nlmsg);
}
int uwsgi_netlink_del(char *iface) {
struct nlmsghdr *nlmsg = uwsgi_netlink_alloc();
struct uwsgi_nl_req *unr = (struct uwsgi_nl_req *)nlmsg;
int index = if_nametoindex(iface);
if (!index) return -1;
nlmsg->nlmsg_type = RTM_DELLINK;
unr->ifinfomsg.ifi_index = index;
return uwsgi_nl_send(nlmsg);
}
int uwsgi_netlink_veth(char *veth0, char *veth1) {
struct rtattr *rta, *rta0, *rta1, *rta2;
struct nlmsghdr *nlmsg = uwsgi_netlink_alloc();
nlmsg->nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL;
// IFLA_LINKINFO
rta0 = NLMSG_TAIL(nlmsg);
rta0->rta_type = IFLA_LINKINFO;
rta0->rta_len = RTA_LENGTH(0);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta0->rta_len);
// IFLA_INFO_KIND
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = IFLA_INFO_KIND;
rta->rta_len = RTA_LENGTH(4);
memcpy(RTA_DATA(rta), "veth", 4);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
// IFLA_INFO_DATA
rta1 = NLMSG_TAIL(nlmsg);
rta1->rta_type = IFLA_INFO_DATA;
rta1->rta_len = RTA_LENGTH(0);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta1->rta_len);
// VETH_INFO_PEER
rta2 = NLMSG_TAIL(nlmsg);
rta2->rta_type = VETH_INFO_PEER;
rta2->rta_len = RTA_LENGTH(0);
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta2->rta_len);
nlmsg->nlmsg_len += sizeof(struct ifinfomsg);
// IFLA_IFNAME
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = IFLA_IFNAME;
rta->rta_len = RTA_LENGTH(strlen(veth1));
memcpy(RTA_DATA(rta), veth1, strlen(veth1));
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
rta2->rta_len = (void *)NLMSG_TAIL(nlmsg) - (void *)rta2;
rta1->rta_len = (void *)NLMSG_TAIL(nlmsg) - (void *)rta1;
rta0->rta_len = (void *)NLMSG_TAIL(nlmsg) - (void *)rta0;
// IFLA_IFNAME
rta = NLMSG_TAIL(nlmsg);
rta->rta_type = IFLA_IFNAME;
rta->rta_len = RTA_LENGTH(strlen(veth0));
memcpy(RTA_DATA(rta), veth0, strlen(veth0));
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
return uwsgi_nl_send(nlmsg);
}
int uwsgi_nl_send(struct nlmsghdr *nlmsg) {
struct sockaddr_nl nladdr;
struct iovec iov = {
.iov_base = (void*)nlmsg,
.iov_len = nlmsg->nlmsg_len,
};
struct msghdr msg = {
.msg_name = &nladdr,
.msg_namelen = sizeof(nladdr),
.msg_iov = &iov,
.msg_iovlen = 1,
};
int ret;
int nlfd;
memset(&nladdr, 0, sizeof(struct sockaddr_nl));
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = 0;
nladdr.nl_groups = 0;
nlfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (nlfd < 0) {
uwsgi_error("socket()");
free(nlmsg);
return -1;
}
ret = sendmsg(nlfd, &msg, 0);
if (ret < 0) {
uwsgi_error("sendmsg()");
free(nlmsg);
close(nlfd);
return -1;
}
ret = recvmsg(nlfd, &msg, 0);
if (ret < 0) {
uwsgi_error("recvmsg()");
free(nlmsg);
close(nlfd);
return -1;
}
if (nlmsg->nlmsg_type == NLMSG_ERROR) {
struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(nlmsg);
ret = err->error;
}
free(nlmsg);
close(nlfd);
return ret;
}
+284
View File
@@ -0,0 +1,284 @@
/*
*** uWSGI, stripped down version of Linux rbtree ***
Red Black Trees
(C) 1999 Andrea Arcangeli <andrea@suse.de>
(C) 2002 David Woodhouse <dwmw2@infradead.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../uwsgi.h"
static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
{
struct rb_node *right = node->rb_right;
struct rb_node *parent = rb_parent(node);
if ((node->rb_right = right->rb_left))
rb_set_parent(right->rb_left, node);
right->rb_left = node;
rb_set_parent(right, parent);
if (parent)
{
if (node == parent->rb_left)
parent->rb_left = right;
else
parent->rb_right = right;
}
else
root->rb_node = right;
rb_set_parent(node, right);
}
static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
{
struct rb_node *left = node->rb_left;
struct rb_node *parent = rb_parent(node);
if ((node->rb_left = left->rb_right))
rb_set_parent(left->rb_right, node);
left->rb_right = node;
rb_set_parent(left, parent);
if (parent)
{
if (node == parent->rb_right)
parent->rb_right = left;
else
parent->rb_left = left;
}
else
root->rb_node = left;
rb_set_parent(node, left);
}
void rb_insert_color(struct rb_node *node, struct rb_root *root)
{
struct rb_node *parent, *gparent;
while ((parent = rb_parent(node)) && rb_is_red(parent))
{
gparent = rb_parent(parent);
if (parent == gparent->rb_left)
{
{
register struct rb_node *uncle = gparent->rb_right;
if (uncle && rb_is_red(uncle))
{
rb_set_black(uncle);
rb_set_black(parent);
rb_set_red(gparent);
node = gparent;
continue;
}
}
if (parent->rb_right == node)
{
register struct rb_node *tmp;
__rb_rotate_left(parent, root);
tmp = parent;
parent = node;
node = tmp;
}
rb_set_black(parent);
rb_set_red(gparent);
__rb_rotate_right(gparent, root);
} else {
{
register struct rb_node *uncle = gparent->rb_left;
if (uncle && rb_is_red(uncle))
{
rb_set_black(uncle);
rb_set_black(parent);
rb_set_red(gparent);
node = gparent;
continue;
}
}
if (parent->rb_left == node)
{
register struct rb_node *tmp;
__rb_rotate_right(parent, root);
tmp = parent;
parent = node;
node = tmp;
}
rb_set_black(parent);
rb_set_red(gparent);
__rb_rotate_left(gparent, root);
}
}
rb_set_black(root->rb_node);
}
static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
struct rb_root *root)
{
struct rb_node *other;
while ((!node || rb_is_black(node)) && node != root->rb_node)
{
if (parent->rb_left == node)
{
other = parent->rb_right;
if (rb_is_red(other))
{
rb_set_black(other);
rb_set_red(parent);
__rb_rotate_left(parent, root);
other = parent->rb_right;
}
if ((!other->rb_left || rb_is_black(other->rb_left)) &&
(!other->rb_right || rb_is_black(other->rb_right)))
{
rb_set_red(other);
node = parent;
parent = rb_parent(node);
}
else
{
if (!other->rb_right || rb_is_black(other->rb_right))
{
rb_set_black(other->rb_left);
rb_set_red(other);
__rb_rotate_right(other, root);
other = parent->rb_right;
}
rb_set_color(other, rb_color(parent));
rb_set_black(parent);
rb_set_black(other->rb_right);
__rb_rotate_left(parent, root);
node = root->rb_node;
break;
}
}
else
{
other = parent->rb_left;
if (rb_is_red(other))
{
rb_set_black(other);
rb_set_red(parent);
__rb_rotate_right(parent, root);
other = parent->rb_left;
}
if ((!other->rb_left || rb_is_black(other->rb_left)) &&
(!other->rb_right || rb_is_black(other->rb_right)))
{
rb_set_red(other);
node = parent;
parent = rb_parent(node);
}
else
{
if (!other->rb_left || rb_is_black(other->rb_left))
{
rb_set_black(other->rb_right);
rb_set_red(other);
__rb_rotate_left(other, root);
other = parent->rb_left;
}
rb_set_color(other, rb_color(parent));
rb_set_black(parent);
rb_set_black(other->rb_left);
__rb_rotate_right(parent, root);
node = root->rb_node;
break;
}
}
}
if (node)
rb_set_black(node);
}
void rb_erase(struct rb_node *node, struct rb_root *root)
{
struct rb_node *child, *parent;
int color;
if (!node->rb_left)
child = node->rb_right;
else if (!node->rb_right)
child = node->rb_left;
else
{
struct rb_node *old = node, *left;
node = node->rb_right;
while ((left = node->rb_left) != NULL)
node = left;
if (rb_parent(old)) {
if (rb_parent(old)->rb_left == old)
rb_parent(old)->rb_left = node;
else
rb_parent(old)->rb_right = node;
} else
root->rb_node = node;
child = node->rb_right;
parent = rb_parent(node);
color = rb_color(node);
if (parent == old) {
parent = node;
} else {
if (child)
rb_set_parent(child, parent);
parent->rb_left = child;
node->rb_right = old->rb_right;
rb_set_parent(old->rb_right, node);
}
node->rb_parent_color = old->rb_parent_color;
node->rb_left = old->rb_left;
rb_set_parent(old->rb_left, node);
goto color;
}
parent = rb_parent(node);
color = rb_color(node);
if (child)
rb_set_parent(child, parent);
if (parent)
{
if (parent->rb_left == node)
parent->rb_left = child;
else
parent->rb_right = child;
}
else
root->rb_node = child;
color:
if (color == RB_BLACK)
__rb_erase_color(child, parent, root);
}
+68
View File
@@ -0,0 +1,68 @@
/*
*** uWSGI, stripped down version of Linux rbtree ***
Red Black Trees
(C) 1999 Andrea Arcangeli <andrea@suse.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
struct rb_node
{
unsigned long rb_parent_color;
#define RB_RED 0
#define RB_BLACK 1
struct rb_node *rb_right;
struct rb_node *rb_left;
} __attribute__((aligned(sizeof(long))));
/* The alignment might seem pointless, but allegedly CRIS needs it */
struct rb_root
{
struct rb_node *rb_node;
};
#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
#define rb_color(r) ((r)->rb_parent_color & 1)
#define rb_is_red(r) (!rb_color(r))
#define rb_is_black(r) rb_color(r)
#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
{
rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
}
static inline void rb_set_color(struct rb_node *rb, int color)
{
rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
}
void rb_insert_color(struct rb_node *, struct rb_root *);
void rb_erase(struct rb_node *, struct rb_root *);
static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
struct rb_node ** rb_link)
{
node->rb_parent_color = (unsigned long )parent;
node->rb_left = node->rb_right = NULL;
*rb_link = node;
}
+29
View File
@@ -0,0 +1,29 @@
/* function written by Ben Taylor (found in the qemu-devel list) */
#include "../uwsgi.h"
time_t timegm(struct tm *t) {
time_t tl, tb;
struct tm *tg;
tl = mktime (t);
if (tl == -1) {
t->tm_hour--;
tl = mktime (t);
if (tl == -1)
return -1; /* can't deal with output from strptime */
tl += 3600;
}
tg = gmtime (&tl);
tg->tm_isdst = 0;
tb = mktime (tg);
if (tb == -1) {
tg->tm_hour--;
tb = mktime (tg);
if (tb == -1)
return -1; /* can't deal with output from gmtime */
tb += 3600;
}
return (tl - (tb - tl));
}
+234 -228
View File
@@ -38,7 +38,7 @@
#ifdef __linux__
#include <endian.h>
#elif __sun__
#elif __apple__
#elif __APPLE__
#include <libkern/OSByteOrder.h>
#else
#include <machine/endian.h>
@@ -47,7 +47,7 @@
#ifdef __BIG_ENDIAN__
static uint16_t uwsgi_swap16(uint16_t x) {
return (uint16_t) ((x & 0xff) << 8 | (x & 0xff00) >> 8);
return (uint16_t) ((x & 0xff) << 8 | (x & 0xff00) >> 8);
}
#endif
@@ -64,7 +64,7 @@ typedef struct __attribute__((packed)) {
uint8_t modifier1;
uint16_t pktsize;
uint8_t modifier2;
} uwsgi_header ;
} uwsgi_header;
typedef struct {
array *extensions;
@@ -394,7 +394,7 @@ static int uwsgi_establish_connection(server *srv, handler_ctx *hctx) {
static void uwsgi_add_var(buffer *b, char * key, uint16_t keylen, char *val, uint16_t vallen) {
#ifdef __BIG_ENDIAN__
uint16_t uwlen ;
uint16_t uwlen;
uwlen = uwsgi_swap16(keylen);
buffer_append_memory(b, (char *) &uwlen, 2); buffer_append_memory(b, key, keylen);
@@ -405,19 +405,19 @@ static void uwsgi_add_var(buffer *b, char * key, uint16_t keylen, char *val, uin
buffer_append_memory(b, (char *) &vallen, 2); buffer_append_memory(b, val, vallen);
#endif
}
static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
size_t i;
char buf[32];
uwsgi_header *uh ;
uwsgi_header *uh;
const char *s;
#ifdef HAVE_IPV6
char b2[INET6_ADDRSTRLEN + 1];
#endif
connection *con = hctx->remote_conn;
server_socket *srv_sock = con->srv_socket;
@@ -436,53 +436,59 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
if (!buffer_is_empty(con->uri.query)) {
uwsgi_add_var(b, "QUERY_STRING", 12, con->uri.query->ptr, con->uri.query->used-1);
} else {
} else {
uwsgi_add_var(b, "QUERY_STRING", 12, "", 0);
}
}
s = get_http_version_name(con->request.http_version);
uwsgi_add_var(b, "SERVER_PROTOCOL", 15, (char *) s, strlen(s));
if (con->server_name->used) {
size_t len = con->server_name->used - 1;
char *colon = strchr(con->server_name->ptr, ':');
if (colon) len = colon - con->server_name->ptr;
size_t len = con->server_name->used - 1;
char *colon = strchr(con->server_name->ptr, ':');
if (colon) len = colon - con->server_name->ptr;
uwsgi_add_var(b, "SERVER_NAME", 11, con->server_name->ptr, len);
} else {
} else {
#ifdef HAVE_IPV6
s = inet_ntop(srv_sock->addr.plain.sa_family,
srv_sock->addr.plain.sa_family == AF_INET6 ?
(const void *) &(srv_sock->addr.ipv6.sin6_addr) :
(const void *) &(srv_sock->addr.ipv4.sin_addr),
b2, sizeof(b2)-1);
s = inet_ntop(srv_sock->addr.plain.sa_family,
srv_sock->addr.plain.sa_family == AF_INET6 ?
(const void *) &(srv_sock->addr.ipv6.sin6_addr) :
(const void *) &(srv_sock->addr.ipv4.sin_addr),
b2, sizeof(b2)-1);
#else
s = inet_ntoa(srv_sock->addr.ipv4.sin_addr);
s = inet_ntoa(srv_sock->addr.ipv4.sin_addr);
#endif
uwsgi_add_var(b, "SERVER_NAME", 11, (char *)s, strlen(s));
}
}
LI_ltostr(buf,
#ifdef HAVE_IPV6
ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
#else
ntohs(srv_sock->addr.ipv4.sin_port)
ntohs(srv_sock->addr.ipv4.sin_port)
#endif
);
);
uwsgi_add_var(b, "SERVER_PORT", 11, buf, strlen(buf));
uwsgi_add_var(b, "REQUEST_URI", 11, con->request.orig_uri->ptr, con->request.orig_uri->used-1);
LI_ltostr(buf,
#ifdef HAVE_IPV6
ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
#else
ntohs(con->dst_addr.ipv4.sin_port)
ntohs(con->dst_addr.ipv4.sin_port)
#endif
);
);
uwsgi_add_var(b, "REMOTE_PORT", 11, buf, strlen(buf));
if (!buffer_is_empty(con->authed_user)) {
uwsgi_add_var(b, "REMOTE_USER", 11,
CONST_BUF_LEN(con->authed_user));
}
s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
uwsgi_add_var(b, "REMOTE_ADDR", 11, (char *)s, strlen(s));
@@ -490,18 +496,18 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
if (hctx->path_info_offset > 1) {
uwsgi_add_var(b, "SCRIPT_NAME", 11, con->uri.path->ptr, hctx->path_info_offset);
if (strlen(con->uri.path->ptr + hctx->path_info_offset) > 0) {
uwsgi_add_var(b, "PATH_INFO", 9, con->request.orig_uri->ptr + hctx->path_info_offset, strlen(con->request.orig_uri->ptr + hctx->path_info_offset));
uwsgi_add_var(b, "PATH_INFO", 9, con->uri.path->ptr + hctx->path_info_offset, strlen(con->uri.path->ptr + hctx->path_info_offset));
}
else {
uwsgi_add_var(b, "PATH_INFO", 9, "/", 1);
}
}
else {
uwsgi_add_var(b, "SCRIPT_NAME", 11, "", 0) ;
uwsgi_add_var(b, "PATH_INFO", 9, con->request.orig_uri->ptr, con->request.orig_uri->used-1) ;
uwsgi_add_var(b, "SCRIPT_NAME", 11, "", 0);
uwsgi_add_var(b, "PATH_INFO", 9, con->uri.path->ptr, strlen(con->uri.path->ptr));
}
for (i = 0; i < con->request.headers->used; i++) {
data_string *ds;
ds = (data_string *)con->request.headers->data[i];
@@ -518,7 +524,7 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
}
for (j = 0; j < ds->key->used - 1; j++) {
srv->tmp_buf->ptr[srv->tmp_buf->used++] = light_isalpha(ds->key->ptr[j]) ? ds->key->ptr[j] & ~32 : '_';
}
}
srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
uwsgi_add_var(b, srv->tmp_buf->ptr, srv->tmp_buf->used-1, ds->value->ptr, ds->value->used-1);
}
@@ -540,19 +546,19 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
}
}
uh = (uwsgi_header *) b->ptr ;
uh->modifier1 = (uint8_t) 0 ;
uh = (uwsgi_header *) b->ptr;
uh->modifier1 = (uint8_t) 0;
#ifdef __BIG_ENDIAN__
uh->pktsize = uwsgi_swap16((uint16_t) b->used - 4) ;
uh->pktsize = uwsgi_swap16((uint16_t) b->used - 4);
#else
uh->pktsize = b->used - 4 ;
uh->pktsize = b->used - 4;
#endif
uh->modifier2 = (uint8_t) 0 ;
uh->modifier2 = (uint8_t) 0;
b->used++; /* fix size */
hctx->wb->bytes_in += b->used -1 ;
hctx->wb->bytes_in += b->used -1;
/* body */
if (con->request.content_length) {
@@ -570,37 +576,37 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
* */
switch (req_c->type) {
case FILE_CHUNK:
weHave = req_c->file.length - req_c->offset;
case FILE_CHUNK:
weHave = req_c->file.length - req_c->offset;
if (weHave > weWant) weHave = weWant;
if (weHave > weWant) weHave = weWant;
chunkqueue_append_file(hctx->wb, req_c->file.name, req_c->offset, weHave);
chunkqueue_append_file(hctx->wb, req_c->file.name, req_c->offset, weHave);
req_c->offset += weHave;
req_cq->bytes_out += weHave;
req_c->offset += weHave;
req_cq->bytes_out += weHave;
hctx->wb->bytes_in += weHave;
hctx->wb->bytes_in += weHave;
break;
case MEM_CHUNK:
/* append to the buffer */
weHave = req_c->mem->used - 1 - req_c->offset;
break;
case MEM_CHUNK:
/* append to the buffer */
weHave = req_c->mem->used - 1 - req_c->offset;
if (weHave > weWant) weHave = weWant;
if (weHave > weWant) weHave = weWant;
b = chunkqueue_get_append_buffer(hctx->wb);
buffer_append_memory(b, req_c->mem->ptr + req_c->offset, weHave);
b->used++; /* add virtual \0 */
b = chunkqueue_get_append_buffer(hctx->wb);
buffer_append_memory(b, req_c->mem->ptr + req_c->offset, weHave);
b->used++; /* add virtual \0 */
req_c->offset += weHave;
req_cq->bytes_out += weHave;
req_c->offset += weHave;
req_cq->bytes_out += weHave;
hctx->wb->bytes_in += weHave;
hctx->wb->bytes_in += weHave;
break;
default:
break;
break;
default:
break;
}
offset += weHave;
@@ -671,29 +677,29 @@ static int uwsgi_response_parse(server *srv, connection *con, plugin_data *p, bu
copy_header = 1;
switch(key_len) {
case 4:
if (0 == strncasecmp(key, "Date", key_len)) {
con->parsed_response |= HTTP_DATE;
}
break;
case 8:
if (0 == strncasecmp(key, "Location", key_len)) {
con->parsed_response |= HTTP_LOCATION;
}
break;
case 10:
if (0 == strncasecmp(key, "Connection", key_len)) {
copy_header = 0;
}
break;
case 14:
if (0 == strncasecmp(key, "Content-Length", key_len)) {
con->response.content_length = strtol(value, NULL, 10);
con->parsed_response |= HTTP_CONTENT_LENGTH;
}
break;
default:
break;
case 4:
if (0 == strncasecmp(key, "Date", key_len)) {
con->parsed_response |= HTTP_DATE;
}
break;
case 8:
if (0 == strncasecmp(key, "Location", key_len)) {
con->parsed_response |= HTTP_LOCATION;
}
break;
case 10:
if (0 == strncasecmp(key, "Connection", key_len)) {
copy_header = 0;
}
break;
case 14:
if (0 == strncasecmp(key, "Content-Length", key_len)) {
con->response.content_length = strtol(value, NULL, 10);
con->parsed_response |= HTTP_CONTENT_LENGTH;
}
break;
default:
break;
}
if (copy_header) {
@@ -731,7 +737,7 @@ static int uwsgi_demux_response(server *srv, handler_ctx *hctx) {
if (p->conf.debug) {
log_error_write(srv, __FILE__, __LINE__, "sd",
"uwsgi - have to read:", b);
"uwsgi - have to read:", b);
}
if (b > 0) {
@@ -785,7 +791,7 @@ static int uwsgi_demux_response(server *srv, handler_ctx *hctx) {
/* enable chunked-transfer-encoding */
if (con->request.http_version == HTTP_VERSION_1_1 &&
!(con->parsed_response & HTTP_CONTENT_LENGTH)) {
!(con->parsed_response & HTTP_CONTENT_LENGTH)) {
con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
}
@@ -824,127 +830,127 @@ static handler_t uwsgi_write_request(server *srv, handler_ctx *hctx) {
int ret;
if (!host ||
(!host->host->used || !host->port)) return -1;
(!host->host->used || !host->port)) return -1;
switch(hctx->state) {
case UWSGI_STATE_INIT:
case UWSGI_STATE_INIT:
#if defined(HAVE_IPV6) && defined(HAVE_INET_PTON)
if (strstr(host->host->ptr,":")) {
if (-1 == (hctx->fd = socket(AF_INET6, SOCK_STREAM, 0))) {
log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed: ", strerror(errno));
return HANDLER_ERROR;
}
} else
if (strstr(host->host->ptr,":")) {
if (-1 == (hctx->fd = socket(AF_INET6, SOCK_STREAM, 0))) {
log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed: ", strerror(errno));
return HANDLER_ERROR;
}
} else
#endif
{
if (-1 == (hctx->fd = socket(AF_INET, SOCK_STREAM, 0))) {
log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed: ", strerror(errno));
return HANDLER_ERROR;
}
}
hctx->fde_ndx = -1;
{
if (-1 == (hctx->fd = socket(AF_INET, SOCK_STREAM, 0))) {
log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed: ", strerror(errno));
return HANDLER_ERROR;
}
}
hctx->fde_ndx = -1;
srv->cur_fds++;
srv->cur_fds++;
fdevent_register(srv->ev, hctx->fd, uwsgi_handle_fdevent, hctx);
fdevent_register(srv->ev, hctx->fd, uwsgi_handle_fdevent, hctx);
if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
return HANDLER_ERROR;
}
/* fall through */
case UWSGI_STATE_CONNECT:
/* try to finish the connect() */
if (hctx->state == UWSGI_STATE_INIT) {
/* first round */
switch (uwsgi_establish_connection(srv, hctx)) {
case 1:
uwsgi_set_state(srv, hctx, UWSGI_STATE_CONNECT);
/* connection is in progress, wait for an event and call getsockopt() below */
fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
return HANDLER_WAIT_FOR_EVENT;
case -1:
/* if ECONNREFUSED choose another connection -> FIXME */
hctx->fde_ndx = -1;
if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
return HANDLER_ERROR;
default:
/* everything is ok, go on */
break;
}
} else {
int socket_error;
socklen_t socket_error_len = sizeof(socket_error);
/* we don't need it anymore */
fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
/* fall through */
case UWSGI_STATE_CONNECT:
/* try to finish the connect() */
if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
log_error_write(srv, __FILE__, __LINE__, "ss",
"getsockopt failed:", strerror(errno));
if (hctx->state == UWSGI_STATE_INIT) {
/* first round */
switch (uwsgi_establish_connection(srv, hctx)) {
case 1:
uwsgi_set_state(srv, hctx, UWSGI_STATE_CONNECT);
return HANDLER_ERROR;
/* connection is in progress, wait for an event and call getsockopt() below */
fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
return HANDLER_WAIT_FOR_EVENT;
case -1:
/* if ECONNREFUSED choose another connection -> FIXME */
hctx->fde_ndx = -1;
return HANDLER_ERROR;
default:
/* everything is ok, go on */
break;
}
} else {
int socket_error;
socklen_t socket_error_len = sizeof(socket_error);
/* we don't need it anymore */
fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
/* try to finish the connect() */
if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
log_error_write(srv, __FILE__, __LINE__, "ss",
"getsockopt failed:", strerror(errno));
return HANDLER_ERROR;
}
if (socket_error != 0) {
log_error_write(srv, __FILE__, __LINE__, "ss",
"establishing connection failed:", strerror(socket_error),
"port:", hctx->host->port);
return HANDLER_ERROR;
}
if (p->conf.debug) {
log_error_write(srv, __FILE__, __LINE__, "s", "uwsgi - connect - delayed success");
}
}
if (socket_error != 0) {
log_error_write(srv, __FILE__, __LINE__, "ss",
"establishing connection failed:", strerror(socket_error),
"port:", hctx->host->port);
return HANDLER_ERROR;
}
if (p->conf.debug) {
log_error_write(srv, __FILE__, __LINE__, "s", "uwsgi - connect - delayed success");
}
}
uwsgi_set_state(srv, hctx, UWSGI_STATE_PREPARE_WRITE);
/* fall through */
case UWSGI_STATE_PREPARE_WRITE:
uwsgi_create_env(srv, hctx);
uwsgi_set_state(srv, hctx, UWSGI_STATE_PREPARE_WRITE);
/* fall through */
case UWSGI_STATE_PREPARE_WRITE:
uwsgi_create_env(srv, hctx);
uwsgi_set_state(srv, hctx, UWSGI_STATE_WRITE);
uwsgi_set_state(srv, hctx, UWSGI_STATE_WRITE);
/* fall through */
case UWSGI_STATE_WRITE:;
ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
/* fall through */
case UWSGI_STATE_WRITE:;
ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
chunkqueue_remove_finished_chunks(hctx->wb);
chunkqueue_remove_finished_chunks(hctx->wb);
if (-1 == ret) { /* error on our side */
log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
if (-1 == ret) { /* error on our side */
log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
return HANDLER_WAIT_FOR_EVENT;
} else if (-2 == ret) { /* remote close */
log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed, remote connection close:", strerror(errno), errno);
return HANDLER_WAIT_FOR_EVENT;
} else if (-2 == ret) { /* remote close */
log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed, remote connection close:", strerror(errno), errno);
return HANDLER_WAIT_FOR_EVENT;
}
return HANDLER_WAIT_FOR_EVENT;
}
if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
uwsgi_set_state(srv, hctx, UWSGI_STATE_READ);
if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
uwsgi_set_state(srv, hctx, UWSGI_STATE_READ);
fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
} else {
fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
} else {
fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
return HANDLER_WAIT_FOR_EVENT;
}
return HANDLER_WAIT_FOR_EVENT;
}
return HANDLER_WAIT_FOR_EVENT;
case UWSGI_STATE_READ:
/* waiting for a response */
return HANDLER_WAIT_FOR_EVENT;
default:
log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
return HANDLER_ERROR;
return HANDLER_WAIT_FOR_EVENT;
case UWSGI_STATE_READ:
/* waiting for a response */
return HANDLER_WAIT_FOR_EVENT;
default:
log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
return HANDLER_ERROR;
}
return HANDLER_GO_ON;
@@ -1000,36 +1006,36 @@ SUBREQUEST_FUNC(mod_uwsgi_handle_subrequest) {
/* ok, create the request */
switch(uwsgi_write_request(srv, hctx)) {
case HANDLER_ERROR:
log_error_write(srv, __FILE__, __LINE__, "sbdd", "uwsgi-server disabled:",
host->host,
host->port,
hctx->fd);
case HANDLER_ERROR:
log_error_write(srv, __FILE__, __LINE__, "sbdd", "uwsgi-server disabled:",
host->host,
host->port,
hctx->fd);
/* disable this server */
host->is_disabled = 1;
host->disable_ts = srv->cur_ts;
/* disable this server */
host->is_disabled = 1;
host->disable_ts = srv->cur_ts;
uwsgi_connection_close(srv, hctx);
uwsgi_connection_close(srv, hctx);
/* reset the enviroment and restart the sub-request */
buffer_reset(con->physical.path);
con->mode = DIRECT;
/* reset the enviroment and restart the sub-request */
buffer_reset(con->physical.path);
con->mode = DIRECT;
joblist_append(srv, con);
joblist_append(srv, con);
/* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
* and hope that the childs will be restarted
*
*/
/* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
* and hope that the childs will be restarted
*
*/
return HANDLER_WAIT_FOR_FD;
case HANDLER_WAIT_FOR_EVENT:
return HANDLER_WAIT_FOR_EVENT;
case HANDLER_WAIT_FOR_FD:
return HANDLER_WAIT_FOR_FD;
default:
break;
return HANDLER_WAIT_FOR_FD;
case HANDLER_WAIT_FOR_EVENT:
return HANDLER_WAIT_FOR_EVENT;
case HANDLER_WAIT_FOR_FD:
return HANDLER_WAIT_FOR_FD;
default:
break;
}
if (con->file_started == 1) {
@@ -1047,7 +1053,7 @@ static handler_t uwsgi_handle_fdevent(void *s, void *ctx, int revents) {
if ((revents & FDEVENT_IN) &&
hctx->state == UWSGI_STATE_READ) {
hctx->state == UWSGI_STATE_READ) {
if (p->conf.debug) {
log_error_write(srv, __FILE__, __LINE__, "sd",
@@ -1055,29 +1061,29 @@ static handler_t uwsgi_handle_fdevent(void *s, void *ctx, int revents) {
}
switch (uwsgi_demux_response(srv, hctx)) {
case 0:
break;
case 1:
hctx->host->usage--;
case 0:
break;
case 1:
hctx->host->usage--;
/* we are done */
uwsgi_connection_close(srv, hctx);
/* we are done */
uwsgi_connection_close(srv, hctx);
joblist_append(srv, con);
return HANDLER_FINISHED;
case -1:
if (con->file_started == 0) {
/* nothing has been send out yet, send a 500 */
connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
con->http_status = 500;
con->mode = DIRECT;
} else {
/* response might have been already started, kill the connection */
connection_set_state(srv, con, CON_STATE_ERROR);
}
joblist_append(srv, con);
return HANDLER_FINISHED;
case -1:
if (con->file_started == 0) {
/* nothing has been send out yet, send a 500 */
connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
con->http_status = 500;
con->mode = DIRECT;
} else {
/* response might have been already started, kill the connection */
connection_set_state(srv, con, CON_STATE_ERROR);
}
joblist_append(srv, con);
return HANDLER_FINISHED;
joblist_append(srv, con);
return HANDLER_FINISHED;
}
}
@@ -1088,7 +1094,7 @@ static handler_t uwsgi_handle_fdevent(void *s, void *ctx, int revents) {
}
if (hctx->state == UWSGI_STATE_CONNECT ||
hctx->state == UWSGI_STATE_WRITE) {
hctx->state == UWSGI_STATE_WRITE) {
/* we are allowed to send something out
*
* 1. in a unfinished connect() call
@@ -1189,7 +1195,7 @@ static handler_t mod_uwsgi_check_extension(server *srv, connection *con, void *p
/* check extension in the form "/uwsgi_pattern" */
if (*(ext->key->ptr) == '/') {
if (strncmp(fn->ptr, ext->key->ptr, ct_len) == 0) {
path_info_offset = ct_len ;
path_info_offset = ct_len;
extension = ext;
break;
}
@@ -1314,7 +1320,7 @@ TRIGGER_FUNC(mod_uwsgi_trigger) {
data_uwsgi *host = (data_uwsgi *)extension->value->data[n];
if (!host->is_disabled ||
srv->cur_ts - host->disable_ts < 5) continue;
srv->cur_ts - host->disable_ts < 5) continue;
log_error_write(srv, __FILE__, __LINE__, "sbd",
"uwsgi - re-enabled:",
+195
View File
@@ -0,0 +1,195 @@
#include "uwsgi.h"
#ifdef UWSGI_LOCK_USE_MUTEX
#define UWSGI_LOCK_SIZE sizeof(pthread_mutexattr_t) + sizeof(pthread_mutex_t)
#define UWSGI_RWLOCK_SIZE sizeof(pthread_rwlockattr_t) + sizeof(pthread_rwlock_t)
// REMEMBER lock must contains space for both pthread_mutex_t and pthread_mutexattr_t !!!
void uwsgi_lock_init(void *lock) {
if (pthread_mutexattr_init((pthread_mutexattr_t *) lock)) {
uwsgi_log("unable to allocate mutexattr structure\n");
exit(1);
}
if (pthread_mutexattr_setpshared((pthread_mutexattr_t *) lock, PTHREAD_PROCESS_SHARED)) {
uwsgi_log("unable to share mutex\n");
exit(1);
}
if (pthread_mutex_init((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t), (pthread_mutexattr_t *) lock)) {
uwsgi_log("unable to initialize mutex\n");
exit(1);
}
}
void uwsgi_rlock(void *lock) {
pthread_rwlock_rdlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
}
void uwsgi_wlock(void *lock) {
pthread_rwlock_wrlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
}
void uwsgi_rwunlock(void *lock) {
pthread_rwlock_unlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
}
void uwsgi_lock(void *lock) {
pthread_mutex_lock((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t));
}
void uwsgi_unlock(void *lock) {
pthread_mutex_unlock((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t));
}
void uwsgi_rwlock_init(void *lock) {
if (pthread_rwlockattr_init((pthread_rwlockattr_t *) lock)) {
uwsgi_log("unable to allocate rwlock structure\n");
exit(1);
}
if (pthread_rwlockattr_setpshared((pthread_rwlockattr_t *) lock, PTHREAD_PROCESS_SHARED)) {
uwsgi_log("unable to share rwlock\n");
exit(1);
}
if (pthread_rwlock_init((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t), (pthread_rwlockattr_t *) lock)) {
uwsgi_log("unable to initialize rwlock\n");
exit(1);
}
}
#endif
#ifdef UWSGI_LOCK_USE_UMTX
#include <machine/atomic.h>
#include <sys/umtx.h>
#define UWSGI_LOCK_SIZE sizeof(struct umtx)
#define UWSGI_RWLOCK_SIZE sizeof(struct umtx)
void uwsgi_rwlock_init(void *lock) { uwsgi_lock_init(lock) ;}
void uwsgi_rlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_wlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_rwunlock(void *lock) { uwsgi_unlock(lock); }
void uwsgi_lock_init(void *lock) {
umtx_init((struct umtx*) lock);
}
void uwsgi_lock(void *lock) {
umtx_lock(lock, 1);
}
void uwsgi_unlock(void *lock) {
umtx_unlock(lock, 1);
}
#endif
#ifdef UWSGI_LOCK_USE_OSX_SPINLOCK
#define UWSGI_LOCK_SIZE sizeof(OSSpinLock)
#define UWSGI_RWLOCK_SIZE sizeof(OSSpinLock)
void uwsgi_lock_init(void *lock) {
memset(lock, 0, sizeof(OSSpinLock));
}
void uwsgi_lock(void *lock) {
OSSpinLockLock((OSSpinLock *) lock);
}
void uwsgi_unlock(void *lock) {
OSSpinLockUnlock((OSSpinLock *) lock);
}
void uwsgi_rwlock_init(void *lock) { uwsgi_lock_init(lock) ;}
void uwsgi_rlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_wlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_rwunlock(void *lock) { uwsgi_unlock(lock); }
#endif
#ifdef UWSGI_LOCK_USE_FLOCK
#define UWSGI_LOCK_SIZE 8
#define UWSGI_RWLOCK_SIZE 8
void uwsgi_lock_init(void *lock) {
FILE *tf = tmpfile();
int fd;
if (!tf) {
uwsgi_error_open("temp lock file");
exit(1);
}
fd = fileno(tf);
memcpy(lock, &fd, sizeof(int));
}
void uwsgi_lock(void *lock) {
int fd;
memcpy(&fd, lock, sizeof(int));
if (flock(fd, LOCK_EX)) { uwsgi_error("flock()"); }
}
void uwsgi_unlock(void *lock) {
int fd;
memcpy(&fd, lock, sizeof(int));
if (flock(fd, LOCK_UN)) { uwsgi_error("flock()"); }
}
void uwsgi_rwlock_init(void *lock) { uwsgi_lock_init(lock) ;}
void uwsgi_rlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_wlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_rwunlock(void *lock) { uwsgi_unlock(lock); }
#endif
void *uwsgi_mmap_shared_lock() {
void *addr = NULL;
addr = mmap(NULL, UWSGI_LOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (addr == NULL) {
uwsgi_error("mmap()");
exit(1);
}
return addr;
}
void *uwsgi_mmap_shared_rwlock() {
void *addr = NULL;
addr = mmap(NULL, UWSGI_RWLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (addr == NULL) {
uwsgi_error("mmap()");
exit(1);
}
return addr;
}
+104 -44
View File
@@ -1,3 +1,4 @@
#define _NO_UWSGI_RB
#include "uwsgi.h"
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
@@ -12,32 +13,49 @@
#define _FILE_OFFSET_BITS 64
#endif
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
#include <sys/sysctl.h>
#endif
extern struct uwsgi_server uwsgi;
void log_request(struct wsgi_request *wsgi_req) {
// optimize this (please)
char *time_request;
time_t microseconds, microseconds2;
static char *empty = "";
char *first_part = empty;
int rlen;
int app_req = -1;
char *msg2 = " ";
char *via = msg2;
char mempkt[4096];
char logpkt[4096];
struct iovec logvec[4];
int logvecpos = 0;
const char *msecs = "msecs";
const char *micros = "micros";
long int rt;
char *tsize = (char *) msecs;
#ifdef UWSGI_SENDFILE
char *msg1 = " via sendfile() ";
#endif
struct uwsgi_app *wi;
if (wsgi_req->app_id >= 0) {
wi = &uwsgi.wsgi_apps[wsgi_req->app_id];
wi = &uwsgi.apps[wsgi_req->app_id];
if (wi->requests > 0) {
app_req = wi->requests;
}
}
via = msg2;
if (wsgi_req->sendfile_fd > -1) {
#ifdef UWSGI_SENDFILE
if (wsgi_req->sendfile_fd > -1 && wsgi_req->sendfile_obj == wsgi_req->async_result) { //wsgi_req->sendfile_fd_size > 0 ) {
via = msg1;
}
#endif
@@ -46,44 +64,67 @@ void log_request(struct wsgi_request *wsgi_req) {
microseconds = wsgi_req->end_of_request.tv_sec * 1000000 + wsgi_req->end_of_request.tv_usec;
microseconds2 = wsgi_req->start_of_request.tv_sec * 1000000 + wsgi_req->start_of_request.tv_usec;
rt = (long int) (microseconds - microseconds2);
if (uwsgi.log_micros) {
tsize = (char *) micros;
}
else {
rt /= 1000;
}
if (uwsgi.vhost) {
logvec[logvecpos].iov_base = wsgi_req->host;
logvec[logvecpos].iov_len = wsgi_req->host_len;
logvecpos++;
logvec[logvecpos].iov_base = " ";
logvec[logvecpos].iov_len = 1;
logvecpos++;
}
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1) {
#ifndef UNBIT
if (uwsgi.synclog) {
snprintf(uwsgi.sync_page, uwsgi.page_size, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ", uwsgi.workers[uwsgi.mywid].vsz_size, uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024, uwsgi.workers[uwsgi.mywid].rss_size, uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
first_part = uwsgi.sync_page;
}
else {
fprintf(stderr, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ", uwsgi.workers[uwsgi.mywid].vsz_size, uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024, uwsgi.workers[uwsgi.mywid].rss_size, uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
}
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ",
(unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long ) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024,
(unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size, (unsigned long long ) uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
#else
fprintf(stderr, "{address space usage: %lld bytes/%lluMB} ", uwsgi.workers[uwsgi.mywid].vsz_size, uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024);
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} ",
(unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024);
#endif
logvec[logvecpos].iov_base = mempkt;
logvec[logvecpos].iov_len = rlen;
logvecpos++;
}
fprintf(stderr, "%s[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %ld msecs%s(%.*s %d) %d headers in %d bytes (%d async switches on async core %d)\n",
first_part,
uwsgi.mypid,
wsgi_req->app_id,
app_req,
uwsgi.workers[0].requests,
wsgi_req->remote_addr_len, wsgi_req->remote_addr,
wsgi_req->remote_user_len, wsgi_req->remote_user,
wsgi_req->var_cnt,
wsgi_req->uh.pktsize,
24, time_request,
wsgi_req->method_len, wsgi_req->method,
wsgi_req->uri_len, wsgi_req->uri,
(uint64_t) wsgi_req->response_size,
(long int) (microseconds - microseconds2) / 1000,
via,
wsgi_req->protocol_len, wsgi_req->protocol,
wsgi_req->status,
wsgi_req->header_cnt,
wsgi_req->headers_size,
wsgi_req->async_switches, wsgi_req->async_id);
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %ld %s%s(%.*s %d) %d headers in %llu bytes (%d switches on core %d)\n",
(int) uwsgi.mypid,
wsgi_req->app_id,
app_req,
(unsigned long long ) uwsgi.workers[0].requests,
wsgi_req->remote_addr_len, wsgi_req->remote_addr,
wsgi_req->remote_user_len, wsgi_req->remote_user,
wsgi_req->var_cnt,
wsgi_req->uh.pktsize,
24, time_request,
wsgi_req->method_len, wsgi_req->method,
wsgi_req->uri_len, wsgi_req->uri,
(unsigned long long) wsgi_req->response_size,
rt, tsize,
via,
wsgi_req->protocol_len, wsgi_req->protocol,
wsgi_req->status,
wsgi_req->header_cnt,
(unsigned long long) wsgi_req->headers_size,
wsgi_req->switches, wsgi_req->async_id);
logvec[logvecpos].iov_base = logpkt;
logvec[logvecpos].iov_len = rlen;
// do not check for errors
rlen = writev(2, logvec, logvecpos+1);
}
void get_memusage() {
@@ -95,27 +136,27 @@ void get_memusage() {
int i;
procfile = fopen("/proc/self/stat", "r");
if (procfile) {
i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", &uwsgi.workers[uwsgi.mywid].vsz_size, &uwsgi.workers[uwsgi.mywid].rss_size);
i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", (unsigned long long *) &uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long *) &uwsgi.workers[uwsgi.mywid].rss_size);
if (i != 2) {
fprintf(stderr, "warning: invalid record in /proc/self/stat\n");
uwsgi_log( "warning: invalid record in /proc/self/stat\n");
}
fclose(procfile);
}
uwsgi.workers[uwsgi.mywid].rss_size = uwsgi.workers[uwsgi.mywid].rss_size * uwsgi.page_size;
#elif defined (__sun__)
psinfo_t info;
int procfd ;
int procfd;
procfd = open("/proc/self/psinfo", O_RDONLY);
if (procfd >= 0) {
if ( read(procfd, (char *) &info, sizeof(info)) > 0) {
uwsgi.workers[uwsgi.mywid].rss_size = (uint64_t) info.pr_rssize * 1024 ;
uwsgi.workers[uwsgi.mywid].vsz_size = (uint64_t) info.pr_size * 1024 ;
uwsgi.workers[uwsgi.mywid].rss_size = (uint64_t) info.pr_rssize * 1024;
uwsgi.workers[uwsgi.mywid].vsz_size = (uint64_t) info.pr_size * 1024;
}
close(procfd);
}
#elif defined( __APPLE__)
#elif defined(__APPLE__)
/* darwin documentation says that the value are in pages, but they are bytes !!! */
struct task_basic_info t_info;
mach_msg_type_number_t t_size = sizeof(struct task_basic_info);
@@ -128,7 +169,11 @@ void get_memusage() {
kvm_t *kv;
int cnt;
#if defined(__FreeBSD__)
kv = kvm_open(NULL, "/dev/null", NULL, O_RDONLY, NULL);
#else
kv = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
#endif
if (kv) {
#if defined(__FreeBSD__) || defined(__DragonFly__)
@@ -138,18 +183,33 @@ void get_memusage() {
uwsgi.workers[uwsgi.mywid].vsz_size = kproc->ki_size;
uwsgi.workers[uwsgi.mywid].rss_size = kproc->ki_rssize * uwsgi.page_size;
}
#elif defined(__NetBSD__)
#elif defined(__NetBSD__) || defined(__OpenBSD__)
struct kinfo_proc2 *kproc2;
kproc2 = kvm_getproc2(kv, KERN_PROC_PID, uwsgi.mypid, sizeof(struct kinfo_proc2), &cnt);
if (kproc2 && cnt > 0) {
#ifdef __OpenBSD__
uwsgi.workers[uwsgi.mywid].vsz_size = (kproc2->p_vm_dsize + kproc2->p_vm_ssize + kproc2->p_vm_tsize) * uwsgi.page_size;
#else
uwsgi.workers[uwsgi.mywid].vsz_size = kproc2->p_vm_msize * uwsgi.page_size;
#endif
uwsgi.workers[uwsgi.mywid].rss_size = kproc2->p_vm_rssize * uwsgi.page_size;
}
#endif
kvm_close(kv);
}
#elif defined(__HAIKU__)
area_info ai;
int32 cookie;
uwsgi.workers[uwsgi.mywid].vsz_size = 0;
uwsgi.workers[uwsgi.mywid].rss_size = 0;
while(get_next_area_info(0, &cookie, &ai) == B_OK) {
uwsgi.workers[uwsgi.mywid].vsz_size += ai.ram_size;
if ( (ai.protection & B_WRITE_AREA) != 0) {
uwsgi.workers[uwsgi.mywid].rss_size += ai.ram_size;
}
}
#endif
}
+89
View File
@@ -0,0 +1,89 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
struct wsgi_request* threaded_current_wsgi_req() { return pthread_getspecific(uwsgi.tur_key); }
struct wsgi_request* simple_current_wsgi_req() { return uwsgi.wsgi_req; }
void uwsgi_register_loop(char *name, void *loop) {
if (uwsgi.loops_cnt >= MAX_LOOPS) {
uwsgi_log("you can define %d loops at max\n", MAX_LOOPS);
exit(1);
}
uwsgi.loops[uwsgi.loops_cnt].name = name;
uwsgi.loops[uwsgi.loops_cnt].loop = loop;
uwsgi.loops_cnt++;
}
void *uwsgi_get_loop(char *name) {
int i;
for(i=0;i<uwsgi.loops_cnt;i++) {
if (!strcmp(name, uwsgi.loops[i].name)) {
return uwsgi.loops[i].loop;
}
}
return NULL;
}
void *simple_loop(void *arg1) {
long core_id = (long) arg1;
struct wsgi_request *wsgi_req = uwsgi.wsgi_requests[core_id];
int i;
#ifdef UWSGI_THREADING
//PyThreadState *pts;
sigset_t smask;
if (uwsgi.threads > 1) {
pthread_setspecific(uwsgi.tur_key, (void *) wsgi_req);
if (core_id > 0) {
// block all signals on new threads
sigfillset(&smask);
pthread_sigmask(SIG_BLOCK, &smask, NULL);
for(i=0;i<0xFF;i++) {
if (uwsgi.p[i]->init_thread) {
uwsgi.p[i]->init_thread(core_id);
}
}
/*
pts = PyThreadState_New(uwsgi.main_thread->interp);
pthread_setspecific(uwsgi.ut_save_key, (void *) pts);
*/
}
}
#endif
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
UWSGI_CLEAR_STATUS;
wsgi_req_setup(wsgi_req, core_id);
if (wsgi_req_accept(wsgi_req)) {
continue;
}
if (wsgi_req_recv(wsgi_req)) {
continue;
}
uwsgi_close_request(wsgi_req);
}
pthread_exit(NULL);
//never here
return NULL;
}
+1132
View File
File diff suppressed because it is too large Load Diff
+22
View File
@@ -0,0 +1,22 @@
<unbit>
<pippo/>
<pluto>
ciao
ciao
</pluto>
<uwsgi id="unbit.it">
<http>:3333</http>
<module>trac.web.main:dispatch_request</module>
<pluto>ciao</pluto>
<env>TRAC_ENV=/root/uwsgi/utrac</env>
</uwsgi>
<uwsgi id="projects.unbit.it">
<http>:4444</http>
<module>trac.web.main:dispatch_request</module>
</uwsgi>
</unbit>
+26
View File
@@ -0,0 +1,26 @@
import uwsgi
import os
def application(env, start_response):
boundary = 'uwsgi_mjpeg_frame'
start_response('200 Ok', [
('Cache-Control', 'no-cache'),
('Cache-Control', 'private'),
('Pragma', 'no-cache'),
('Content-Type', 'multipart/x-mixed-replace; boundary=' + boundary),
]
)
yield "--%s\n" % boundary
while 1:
yield "Content-Type: image/jpeg\r\n\r\n"
uwsgi.sendfile('screenshot.jpg')
yield "--%s\n" % boundary
#os.system('./isightcapture -w 640 -h 480 screenshot.jpg')
#os.system('screencapture -m -T 1 screenshot.jpg')
+23
View File
@@ -0,0 +1,23 @@
use Mojolicious::Lite;
# /
get '/' => 'index';
# /*
get '/:groovy' => sub {
my $self = shift;
$self->render_text($self->param('groovy'), layout => 'funky');
};
app->start('psgi');
__DATA__
@@ index.html.ep
% layout 'funky';
Yea baby!
@@ layouts/funky.html.ep
<!doctype html><html>
<head><title>Funky!</title></head>
<body><%= content %></body>
</html>
+27
View File
@@ -0,0 +1,27 @@
[uwsgi]
; socket 0
socket = :3033
; socket 1
socket = :3034
; socket 2
socket = pippo1.sock
; socket 3
socket = pippo2.sock
; socket 4
socket = 127.0.0.1:1717
map-socket = 0:1,2,3,4
map-socket = 1:4
map-socket = 2:10
map-socket = 3:5,6,9
map-socket = 4:7,8,9
vacuum = true
memory-report = true
master = true
processes = 10
;mount = /app1=werkzeug.testapp:test_app
;mount = /app2=config:/Users/roberta/uwsgi/my.ini
;mount = /app3=pinaxsite/deploy/pinax.wsgi
+50
View File
@@ -0,0 +1,50 @@
<uwsgi>
<plugins>rack</plugins>
<http>:9090</http>
<socket>:3031</socket>
<socket>127.0.0.1:3032</socket>
<manage-script-name/>
<master/>
<processes>8</processes>
<!--
<vhost/>
<vhost-host/>
-->
<env>TRAC_ENV=utrac</env>
<app mountpoint="/">
<module>werkzeug.testapp:test_app</module>
</app>
<app mountpoint="/trac">
<module>trac.web.main:dispatch_request</module>
</app>
<app mountpoint="/trac/foo">
<module>werkzeug.testapp:test_app</module>
</app>
<app mountpoint="/bzr">
<eval>
from bzrlib.transport.http import wsgi
application = wsgi.make_app("mybzr", "/bzr", readonly=False)
</eval>
</app>
<app domain="sirius002:9090">
<module>trac.web.main:dispatch_request</module>
</app>
<app domain="sirius003:9090">
<rack>config2.ru</rack>
</app>
</uwsgi>
+27
View File
@@ -0,0 +1,27 @@
import werkzeug
def web3_app(environ):
status = b'200 OK'
headers = [(b'Content-type', b'text/plain')]
body = [b'I am a Web3 app\n']
return body, status, headers
def zero_app(e,s):
s('200 OK', [ ('Content-Type', 'text/plain') ])
return ""
def not_found(e,s):
s('404 Not Found', [ ('Content-Type', 'text/plain') ])
return ""
def wsgi_app(e, s):
s('200 OK', [ ('Content-Type', 'text/plain') ])
yield "I am a WSGI app\n"
def internal_server_error(e, s):
s('500 Internal Server Error', [ ('Content-Type', 'text/plain') ])
return ""
applications = {'':web3_app, '/wsgi':wsgi_app, '/test':werkzeug.test_app, '/zero':zero_app, '/notfound':not_found, '/ise':internal_server_error}
-51
View File
@@ -1,51 +0,0 @@
#include "uwsgi.h"
void nagios(struct uwsgi_server *uwsgi) {
struct pollfd nagios_poll;
// connect and send
if (uwsgi->socket_name == NULL) {
fprintf(stdout, "UWSGI UNKNOWN: you have specified an invalid socket\n");
exit(3);
}
char *tcp_port = strchr(uwsgi->socket_name, ':');
if (tcp_port == NULL) {
fprintf(stdout, "UWSGI UNKNOWN: you have specified an invalid socket\n");
exit(3);
}
tcp_port[0] = 0;
nagios_poll.fd = connect_to_tcp(uwsgi->socket_name, atoi(tcp_port + 1), uwsgi->shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (nagios_poll.fd < 0) {
fprintf(stdout, "UWSGI CRITICAL: could not connect() to workers\n");
exit(2);
}
uwsgi->wsgi_req->uh.modifier1 = UWSGI_MODIFIER_PING;
uwsgi->wsgi_req->uh.pktsize = 0;
uwsgi->wsgi_req->uh.modifier2 = 0;
if (write(nagios_poll.fd, uwsgi->wsgi_req, 4) != 4) {
uwsgi_error("write()");
fprintf(stdout, "UWSGI CRITICAL: could not send ping packet to workers\n");
exit(2);
}
nagios_poll.events = POLLIN;
if (!uwsgi_parse_response(&nagios_poll, uwsgi->shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], (struct uwsgi_header *) uwsgi->wsgi_req, uwsgi->wsgi_req->buffer)) {
fprintf(stdout, "UWSGI CRITICAL: timed out waiting for response\n");
exit(2);
}
else {
if (uwsgi->wsgi_req->uh.pktsize > 0) {
fprintf(stdout, "UWSGI WARNING: %.*s\n", uwsgi->wsgi_req->uh.pktsize, uwsgi->wsgi_req->buffer);
exit(1);
}
else {
fprintf(stdout, "UWSGI OK: armed and ready\n");
exit(0);
}
}
// never here
fprintf(stdout, "UWSGI UNKNOWN: probably you hit a bug of uWSGI !!!\n");
exit(3);
}
+1209 -1185
View File
File diff suppressed because it is too large Load Diff
+95
View File
@@ -0,0 +1,95 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
int uwsgi_load_plugin(int modifier, char *plugin, char *pargs, int absolute) {
void *plugin_handle;
char *plugin_name;
char *plugin_entry_symbol;
struct uwsgi_plugin *up;
int i;
char *colon = strchr(plugin, ':');
if (colon) {
colon[0] = 0;
}
check:
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->name) {
if (!strcmp(plugin, uwsgi.p[i]->name)) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 0;
}
}
if (uwsgi.p[i]->alias) {
if (!strcmp(plugin, uwsgi.p[i]->alias)) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 0;
}
}
}
for(i=0;i<uwsgi.gp_cnt;i++) {
if (uwsgi.gp[i]->name) {
if (!strcmp(plugin, uwsgi.gp[i]->name)) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 0;
}
}
if (uwsgi.gp[i]->alias) {
if (!strcmp(plugin, uwsgi.gp[i]->alias)) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 0;
}
}
}
if (colon) {
plugin = colon+1;
colon[0] = ':';
colon = NULL;
goto check;
}
if (absolute) {
plugin_name = malloc(strlen(plugin) + 1);
memcpy(plugin_name, plugin, strlen(plugin) + 1);
}
else {
plugin_name = uwsgi_concat4(UWSGI_PLUGIN_DIR, "/", plugin, "_plugin.so");
}
plugin_handle = dlopen(plugin_name, RTLD_NOW | RTLD_GLOBAL);
free(plugin_name);
if (!plugin_handle) {
uwsgi_log( "%s\n", dlerror());
}
else {
plugin_entry_symbol = uwsgi_concat2(plugin, "_plugin");
up = dlsym(plugin_handle, plugin_entry_symbol);
if (up) {
if (modifier != -1) {
fill_plugin_table(modifier, up);
}
else {
fill_plugin_table(up->modifier1, up);
}
return 1;
}
uwsgi_log( "%s\n", dlerror());
}
return 0;
}
+28
View File
@@ -0,0 +1,28 @@
/* uwsgi ADMIN|10 */
int uwsgi_request_admin(struct wsgi_request *wsgi_req) {
uint32_t opt_value = 0;
int i;
if (wsgi_req->uh.pktsize >= 4) {
memcpy(&opt_value, wsgi_req->buffer, 4);
// TODO: check endianess ?
}
uwsgi_log( "setting internal option %d to %d\n", wsgi_req->uh.modifier2, opt_value);
uwsgi.shared->options[wsgi_req->uh.modifier2] = opt_value;
// ACK
wsgi_req->uh.modifier1 = 255;
wsgi_req->uh.pktsize = 0;
wsgi_req->uh.modifier2 = 1;
i = write(wsgi_req->poll.fd, wsgi_req, 4);
if (i != 4) {
uwsgi_error("write()");
}
return UWSGI_OK;
}
+139
View File
@@ -0,0 +1,139 @@
#include "../../uwsgi.h"
#include <wordexp.h>
extern struct uwsgi_server uwsgi;
char *cgi_docroot;
#define LONG_ARGS_CGI_BASE 17000 + ((9 + 1) * 100)
#define LONG_ARGS_CGI LONG_ARGS_CGI_BASE + 1
struct option uwsgi_cgi_options[] = {
{"cgi", required_argument, 0, LONG_ARGS_CGI},
{0, 0, 0, 0},
};
int uwsgi_cgi_init(){
uwsgi_log("initialized CGI engine\n");
return 1;
}
int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
int i;
pid_t cgi_pid;
int waitpid_status;
char *argv[2];
char full_path[PATH_MAX];
/* Standard CGI request */
if (!wsgi_req->uh.pktsize) {
uwsgi_log("Invalid CGI request. skip.\n");
return -1;
}
if (uwsgi_parse_vars(wsgi_req)) {
uwsgi_log("Invalid CGI request. skip.\n");
return -1;
}
// check for file availability (and 'runnability')
cgi_pid = fork();
if (cgi_pid < 0) {
uwsgi_error("fork()");
return -1;
}
if (cgi_pid > 0) {
// close input
close(wsgi_req->poll.fd);
wsgi_req->fd_closed = 1;
// now wait for fd
if (waitpid(cgi_pid, &waitpid_status ,0) > 0) {
uwsgi_log("CGI FINISHED\n");
}
return 0;
}
// close all the fd except wsgi_req->poll.fd and 2;
for(i=0;i< (int)uwsgi.max_fd;i++) {
if (i != wsgi_req->poll.fd && i != 2) {
close(i);
}
}
// now map wsgi_req->poll.fd to 0 && 1
if (wsgi_req->poll.fd != 0) {
dup2(wsgi_req->poll.fd, 0);
close(wsgi_req->poll.fd);
}
dup2(0,1);
// fill cgi env
for(i=0;i<wsgi_req->var_cnt;i++) {
// no need to free the putenv() memory
if (putenv(uwsgi_concat3n(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len, "=", 1, wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len))) {
uwsgi_error("putenv()");
}
i++;
}
char *path_info = uwsgi_concat4n(cgi_docroot, strlen(cgi_docroot), "/", 1,wsgi_req->path_info, wsgi_req->path_info_len, "", 0);
uwsgi_log("requested %s %s\n", path_info, realpath(path_info, full_path));
argv[0] = full_path;
argv[1] = NULL;
if (execv(argv[0], argv)) {
uwsgi_error("execv()");
}
// never here
exit(1);
return 0;
}
void uwsgi_cgi_after_request(struct wsgi_request *wsgi_req) {
if (uwsgi.shared->options[UWSGI_OPTION_LOGGING])
log_request(wsgi_req);
}
int uwsgi_cgi_manage_options(int i, char *optarg) {
switch(i) {
case LONG_ARGS_CGI:
cgi_docroot = optarg;
return 1;
}
return 0;
}
struct uwsgi_plugin cgi_plugin = {
.name = "cgi",
.modifier1 = 9,
.init = uwsgi_cgi_init,
.options = uwsgi_cgi_options,
.manage_opt = uwsgi_cgi_manage_options,
.request = uwsgi_cgi_request,
.after_request = uwsgi_cgi_after_request,
};
+5
View File
@@ -0,0 +1,5 @@
NAME='cgi'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['cgi_plugin']
+19
View File
@@ -0,0 +1,19 @@
#include "../../uwsgi.h"
extern struct uwsgi_server uwsgi;
int uwsgi_echo_request(struct wsgi_request *wsgi_req) {
wsgi_req->response_size = write(wsgi_req->poll.fd, wsgi_req->buffer, wsgi_req->uh.pktsize);
return 0;
}
struct uwsgi_plugin echo_plugin = {
.name = "echo",
.modifier1 = 101,
.request = uwsgi_echo_request,
};
+6
View File
@@ -0,0 +1,6 @@
NAME='echo'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['echo_plugin']
+455
View File
@@ -0,0 +1,455 @@
#include "../../uwsgi.h"
#include "erlang.h"
extern struct uwsgi_server uwsgi;
struct uwsgi_erlang uerl;
struct option erlang_options[] = {
{"erlang", required_argument, 0, LONG_ARGS_ERLANG},
{"erlang-cookie", required_argument, 0, LONG_ARGS_ERLANG_COOKIE},
{0, 0, 0, 0},
};
void dump_eterm(ei_x_buff *x) {
int etype, esize, arity;
long long num;
char *atom;
int i;
char *binary;
long bin_size;
double fnum;
ei_get_type(x->buff, &x->index, &etype, &esize);
uwsgi_log("etype: %d/%c esize: %d\n", etype, etype, esize);
switch(etype) {
case ERL_SMALL_INTEGER_EXT:
case ERL_INTEGER_EXT:
case ERL_SMALL_BIG_EXT:
case ERL_LARGE_BIG_EXT:
ei_decode_longlong(x->buff, &x->index, &num);
uwsgi_log("num: %lu\n", num);
break;
case ERL_FLOAT_EXT:
ei_decode_double(x->buff, &x->index, &fnum);
uwsgi_log("float: %f\n", fnum);
break;
case ERL_STRING_EXT:
atom = uwsgi_malloc(esize+1);
ei_decode_string(x->buff, &x->index, atom);
uwsgi_log("string: %s\n", atom);
free(atom);
break;
case ERL_ATOM_EXT:
atom = uwsgi_malloc(esize+1);
ei_decode_atom(x->buff, &x->index, atom);
uwsgi_log("atom: %s\n", atom);
free(atom);
break;
case ERL_SMALL_TUPLE_EXT:
case ERL_LARGE_TUPLE_EXT:
ei_decode_tuple_header(x->buff, &x->index, &arity);
for(i=0;i<arity;i++) {
dump_eterm(x);
}
break;
case ERL_LIST_EXT:
case ERL_NIL_EXT:
ei_decode_list_header(x->buff, &x->index, &arity);
if (arity == 0) {
uwsgi_log("nil value\n");
break;
}
for(i=0;i<arity+1;i++) {
dump_eterm(x);
}
break;
case ERL_BINARY_EXT:
binary = uwsgi_malloc(esize);
ei_decode_binary(x->buff, &x->index, binary, &bin_size);
uwsgi_log("binary data of %d bytes\n", bin_size);
free(binary);
break;
default:
uwsgi_log("ignored...\n");
ei_skip_term(x->buff, &x->index);
break;
}
}
void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
int etype, esize;
int arity;
char *gen_call;
char *module;
char *call;
char buffer[0xffff];
char *argv[0xff] ;
int argc;
uint16_t ret;
ei_x_buff xr;
erlang_ref eref;
ei_get_type(x->buff, &x->index, &etype, &esize);
uwsgi_log("%d %c %c %c\n", etype, etype, ERL_SMALL_TUPLE_EXT, ERL_LARGE_TUPLE_EXT);
if (etype != ERL_SMALL_TUPLE_EXT && etype != ERL_LARGE_TUPLE_EXT) return;
uwsgi_log("decode tuple\n");
ei_decode_tuple_header(x->buff, &x->index, &arity);
uwsgi_log("rpc arity %d\n", arity);
if (arity != 3) return ;
ei_get_type(x->buff, &x->index, &etype, &esize);
uwsgi_log("%d %c\n", etype, etype);
if (etype != ERL_ATOM_EXT && etype != ERL_STRING_EXT) return ;
gen_call = uwsgi_malloc(esize);
if (etype == ERL_ATOM_EXT) {
ei_decode_atom(x->buff, &x->index, gen_call);
}
else {
ei_decode_string(x->buff, &x->index, gen_call);
}
uwsgi_log("gen call = %s\n", gen_call);
ei_get_type(x->buff, &x->index, &etype, &esize);
if (etype != ERL_SMALL_TUPLE_EXT) return ;
ei_decode_tuple_header(x->buff, &x->index, &arity);
if (arity != 2) return ;
ei_get_type(x->buff, &x->index, &etype, &esize);
ei_skip_term(x->buff, &x->index);
uwsgi_log("skip0 %d %c\n", etype, etype);
ei_get_type(x->buff, &x->index, &etype, &esize);
uwsgi_log("skip1 %d %c\n", etype, etype);
ei_decode_ref(x->buff, &x->index, &eref);
ei_get_type(x->buff, &x->index, &etype, &esize);
uwsgi_log("%d %c\n", etype, etype);
module = uwsgi_malloc(esize);
if (etype == ERL_ATOM_EXT) {
ei_decode_atom(x->buff, &x->index, module);
}
else {
ei_decode_string(x->buff, &x->index, module);
}
ei_get_type(x->buff, &x->index, &etype, &esize);
uwsgi_log("%d %c\n", etype, etype);
if (etype != ERL_SMALL_TUPLE_EXT) return ;
ei_decode_tuple_header(x->buff, &x->index, &arity);
uwsgi_log("arity: %d\n", arity);
if (arity != 5) return ;
ei_get_type(x->buff, &x->index, &etype, &esize);
uwsgi_log("%d %c\n", etype, etype);
char *method = uwsgi_malloc(esize);
if (etype == ERL_ATOM_EXT) {
ei_decode_atom(x->buff, &x->index, method);
}
else {
ei_decode_string(x->buff, &x->index, method);
}
if (strcmp(method, "call")) return;
ei_get_type(x->buff, &x->index, &etype, &esize);
uwsgi_log("%d %c\n", etype, etype);
if (etype != ERL_ATOM_EXT && etype != ERL_STRING_EXT) return ;
module = uwsgi_malloc(esize);
if (etype == ERL_ATOM_EXT) {
ei_decode_atom(x->buff, &x->index, module);
}
else {
ei_decode_string(x->buff, &x->index, module);
}
ei_get_type(x->buff, &x->index, &etype, &esize);
if (etype != ERL_ATOM_EXT && etype != ERL_STRING_EXT) return ;
call = uwsgi_malloc(esize);
if (etype == ERL_ATOM_EXT) {
ei_decode_atom(x->buff, &x->index, call);
}
else {
ei_decode_string(x->buff, &x->index, call);
}
uwsgi_log("RPC %s %s\n", module, call);
ei_get_type(x->buff, &x->index, &etype, &esize);
if (etype == ERL_ATOM_EXT) {
argc = 1;
argv[0] = uwsgi_malloc(esize+1);
ei_decode_atom(x->buff, &x->index, argv[0]);
}
else if (etype == ERL_STRING_EXT) {
argc = 1;
argv[0] = uwsgi_malloc(esize+1);
ei_decode_string(x->buff, &x->index, argv[0]);
}
ret = uwsgi_rpc(call, argc, argv, buffer);
uwsgi_log("buffer: %.*s\n", ret, buffer);
ei_x_new_with_version(&xr);
ei_x_encode_tuple_header(&xr, 2);
//ei_x_encode_atom(&xr, "rex");
ei_x_encode_ref(&xr, &eref);
ei_x_encode_string_len(&xr, buffer, ret);
uwsgi_log("ei_send to %d %s %d %d %d: %d %d\n", fd, from->node, from->num , from->serial, from->creation, xr.index, ei_send(fd, from, xr.buff, xr.index));
//uwsgi_log("ei_send to %d %s %d %d %d: %d %d\n", fd, from->node, from->num , from->serial, from->creation, xr.index, ei_reg_send(&uerl.cnode, fd, "rex", xr.buff, xr.index));
}
void erlang_loop() {
ErlConnect econn;
//ErlMessage em;
erlang_msg em;
int fd;
int eversion;
int i;
ei_x_buff x, xr;
ei_x_new(&x);
ei_x_new(&xr);
/*
int fd0 = ei_connect(&uerl.cnode, "anothernode@maverick64");
uwsgi_log("fd0: %d\n", fd0);
ei_x_encode_list_header(&x, 0);
ei_rpc_to(&uerl.cnode, fd0, "erlang", "node", x.buff, x.index);
ei_rpc_from(&uerl.cnode, fd0, 10000, &em, &xr);
uwsgi_log("From: %s To: %s RegName: %s\n", em.from.node, em.to.node, em.toname);
xr.index = 0;
ei_decode_version(xr.buff, &xr.index, &eversion);
uwsgi_log("eversion: %d\n", eversion);
dump_eterm(&xr);
*/
for(;;) {
fd = ei_accept(&uerl.cnode, uerl.fd, &econn);
if (fd >= 0) {
for (;;) {
if (ei_xreceive_msg(fd, &em, &x) == ERL_MSG) {
if (em.msgtype == ERL_TICK)
continue;
uwsgi_log("From: %s To: %s RegName: %s\n", em.from.node, em.to.node, em.toname);
x.index = 0;
ei_decode_version(x.buff, &x.index, &eversion);
#ifdef UWSGI_DEBUG
uwsgi_log("eversion: %d\n", eversion);
#endif
if (!strcmp(em.toname, "rex")) {
uwsgi_erlang_rpc(fd, &em.from, &x);
}
else {
int uep = -1;
for(i=0;i<uerl.uep_cnt;i++) {
if (!strcmp(uerl.uep[i].name, em.toname)) {
uep = i;
break;
}
}
if (uep > -1) {
if (uerl.uep[uep].plugin) {
uerl.uep[uep].plugin( uerl.uep[uep].func, &x );
}
}
else {
uwsgi_log("!!! unregistered erlang process requested, dumping it !!!\n");
dump_eterm(&x);
}
}
/*
if (em.msgtype) {
dump_erl_obj(em.msg);
erl_free_compound(em.msg);
}
if (em.to) {
uwsgi_log("*** TO ***\n");
dump_erl_obj(em.to);
erl_free_compound(em.to);
}
if (em.from) {
uwsgi_log("*** FROM ***\n");
dump_erl_obj(em.from);
erl_free_compound(em.from);
}
*/
}
else {
break;
}
}
close(fd);
}
}
}
int erlang_init() {
char *host;
struct sockaddr_in sin;
socklen_t slen = sizeof(struct sockaddr_in);
char *ip = NULL;
char *nodename;
struct in_addr addr;
uerl.lock = uwsgi_mmap_shared_lock();
uwsgi_lock_init(uerl.lock);
if (uerl.name) {
uwsgi.master_process = 1;
host = strchr(uerl.name, '@');
if (!host) {
if (ei_connect_init(&uerl.cnode, uerl.name, uerl.cookie, 0) < 0) {
uwsgi_log("unable to initialize erlang connection\n");
exit(1);
}
}
else {
nodename = uwsgi_concat2n(uerl.name, host-uerl.name, "",0);
ip = uwsgi_resolve_ip(host+1);
if (ip) {
#ifdef UWSGI_DEBUG
uwsgi_log("ip: %s\n", ip);
#endif
addr.s_addr = inet_addr(ip);
if (ei_connect_xinit(&uerl.cnode, host+1, nodename, uerl.name, &addr, uerl.cookie, 0) < 0) {
uwsgi_log("unable to initialize erlang connection\n");
exit(1);
}
}
else {
if (ei_connect_init(&uerl.cnode, nodename, uerl.cookie, 0) < 0) {
uwsgi_log("unable to initialize erlang connection\n");
exit(1);
}
}
free(nodename);
}
if (ip) {
uerl.fd = bind_to_tcp(ip, uwsgi.listen_queue, NULL);
}
else {
uerl.fd = bind_to_tcp("", uwsgi.listen_queue, NULL);
}
if (uerl.fd < 0) {
exit(1);
}
if (getsockname(uerl.fd, (struct sockaddr *) &sin, &slen)) {
uwsgi_error("getsockname()");
exit(1);
}
if (ei_publish(&uerl.cnode, ntohs(sin.sin_port)) < 0) {
uwsgi_log( "*** unable to subscribe with EPMD ***\n");
exit(1);
}
uwsgi_log("Erlang C-Node %s registered on port %d\n", ei_thisnodename(&uerl.cnode), ntohs(sin.sin_port));
if (register_fat_gateway("erlang", erlang_loop) == NULL) {
uwsgi_log("unable to register the erlang gateway\n");
exit(1);
}
}
return 0;
}
int erlang_opt(int i, char *optarg) {
switch(i) {
case LONG_ARGS_ERLANG:
uerl.name = optarg;
return 1;
case LONG_ARGS_ERLANG_COOKIE:
uerl.cookie = optarg;
return 1;
}
return 0;
}
struct uwsgi_plugin erlang_plugin = {
.name = "erlang",
.options = erlang_options,
.manage_opt = erlang_opt,
.init = erlang_init,
};
+30
View File
@@ -0,0 +1,30 @@
#include <ei.h>
#define MAX_UWSGI_ERLANG_PROCESSES 64
#define LONG_ARGS_ERLANG 17012
#define LONG_ARGS_ERLANG_COOKIE 17013
struct uwsgi_erlang_process {
char name[0xff];
void (*plugin)(void *, ei_x_buff *);
void *func;
};
struct uwsgi_erlang {
ei_cnode cnode;
char *name;
char *cookie;
int fd;
void *lock;
struct uwsgi_erlang_process uep[MAX_UWSGI_ERLANG_PROCESSES];
int uep_cnt;
};
+7
View File
@@ -0,0 +1,7 @@
NAME='erlang'
CFLAGS = []
LDFLAGS = []
LIBS = ['-lei']
GCC_LIST = ['erlang']
+8 -6
View File
@@ -1,13 +1,15 @@
#include "../../uwsgi.h"
int uwsgi_init(struct uwsgi_server *uwsgi, char *args){
fprintf(stderr,"i am the example plugin initialization function with arg: %s\n", args);
extern struct uwsgi_server uwsgi;
int uwsgi_init(char *args){
uwsgi_log("i am the example plugin initialization function with arg: %s\n", args);
return 0;
}
int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
int uwsgi_request(struct wsgi_request *wsgi_req) {
char *http = "HTTP/1.1 200 Ok\r\nContent-type: text/html\r\n\r\n<h1>Hello World</h1>" ;
char *http = "HTTP/1.1 200 Ok\r\nContent-type: text/html\r\n\r\n<h1>Hello World</h1>";
wsgi_req->response_size += write(wsgi_req->poll.fd, http, strlen(http));
@@ -15,6 +17,6 @@ int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
}
void uwsgi_after_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
fprintf(stderr,"i am the example plugin after request function\n");
void uwsgi_after_request(struct wsgi_request *wsgi_req) {
uwsgi_log("i am the example plugin after request function\n");
}
+590
View File
@@ -0,0 +1,590 @@
/*
uWSGI fastrouter
requires:
- async
- caching
- pcre (optional)
*/
#include "../../uwsgi.h"
#define LONG_ARGS_FASTROUTER 150001
#define LONG_ARGS_FASTROUTER_EVENTS 150002
#define LONG_ARGS_FASTROUTER_USE_PATTERN 150003
#define LONG_ARGS_FASTROUTER_USE_BASE 150004
#define LONG_ARGS_FASTROUTER_SUBSCRIPTION_SERVER 150005
#define LONG_ARGS_FASTROUTER_TIMEOUT 150006
#define FASTROUTER_STATUS_FREE 0
#define FASTROUTER_STATUS_CONNECTING 1
#define FASTROUTER_STATUS_RECV_HDR 2
#define FASTROUTER_STATUS_RECV_VARS 3
#define FASTROUTER_STATUS_RESPONSE 4
#define add_timeout(x) uwsgi_add_rb_timer(ufr.timeouts, time(NULL)+ufr.socket_timeout, x)
#define del_timeout(x) rb_erase(&x->timeout->rbt, ufr.timeouts); free(x->timeout);
struct uwsgi_fastrouter {
char *socket_name;
int use_cache;
int nevents;
char *pattern;
int pattern_len;
char *base;
int base_len;
char *subscription_server;
struct uwsgi_dict *subscription_dict;
int socket_timeout;
struct rb_root *timeouts;
} ufr;
struct option fastrouter_options[] = {
{"fastrouter", required_argument, 0, LONG_ARGS_FASTROUTER},
{"fastrouter-use-cache", no_argument, &ufr.use_cache, 1},
{"fastrouter-use-pattern", required_argument, 0, LONG_ARGS_FASTROUTER_USE_PATTERN},
{"fastrouter-use-base", required_argument, 0, LONG_ARGS_FASTROUTER_USE_BASE},
{"fastrouter-events", required_argument, 0, LONG_ARGS_FASTROUTER_EVENTS},
{"fastrouter-subscription-server", required_argument, 0, LONG_ARGS_FASTROUTER_SUBSCRIPTION_SERVER},
{"fastrouter-timeout", required_argument, 0, LONG_ARGS_FASTROUTER_TIMEOUT},
{0, 0, 0, 0},
};
extern struct uwsgi_server uwsgi;
void fastrouter_manage_subscription(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
struct uwsgi_subscribe_req *usr = (struct uwsgi_subscribe_req *) data;
if (!uwsgi_strncmp("key", 3, key, keylen)) {
usr->key = val;
usr->keylen = vallen;
}
else if (!uwsgi_strncmp("address", 7, key, keylen)) {
usr->address = val;
usr->address_len = vallen;
}
}
struct fastrouter_session {
int fd;
int instance_fd;
int status;
struct uwsgi_header uh;
uint8_t h_pos;
char buffer[0xffff];
uint16_t pos;
char *hostname;
uint16_t hostname_len;
char *instance_address;
uint64_t instance_address_len;
struct uwsgi_subscriber_name *un;
int pass_fd;
struct uwsgi_rb_timer *timeout;
int instance_failed;
};
static void close_session(struct fastrouter_session **fr_table, struct fastrouter_session *fr_session) {
close(fr_session->fd);
fr_table[fr_session->fd] = NULL;
if (fr_session->instance_fd != -1) {
if (ufr.subscription_server && (fr_session->instance_failed || fr_session->status == FASTROUTER_STATUS_CONNECTING)) {
uwsgi_log("marking %.*s as failed\n", (int) fr_session->instance_address_len,fr_session->instance_address);
fr_session->un->len = 0;
}
close(fr_session->instance_fd);
fr_table[fr_session->instance_fd] = NULL;
}
del_timeout(fr_session);
free(fr_session);
}
static struct uwsgi_rb_timer *reset_timeout(struct fastrouter_session *fr_session) {
del_timeout(fr_session);
return add_timeout(fr_session);
}
static void expire_timeouts(struct fastrouter_session **fr_table) {
time_t current = time(NULL);
struct uwsgi_rb_timer *urbt;
for(;;) {
urbt = uwsgi_min_rb_timer(ufr.timeouts);
if (urbt == NULL) return;
if (urbt->key <= current) {
close_session(fr_table, (struct fastrouter_session *)urbt->data);
uwsgi_log("timeout !!!\n");
continue;
}
break;
}
}
void fr_get_hostname(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
struct fastrouter_session *fr_session = (struct fastrouter_session *) data;
//uwsgi_log("%.*s = %.*s\n", keylen, key, vallen, val);
if (!uwsgi_strncmp("SERVER_NAME", 11, key, keylen) && !fr_session->hostname_len) {
fr_session->hostname = val;
fr_session->hostname_len = vallen;
return;
}
if (!uwsgi_strncmp("HTTP_HOST", 9, key, keylen)) {
fr_session->hostname = val;
fr_session->hostname_len = vallen;
return;
}
}
struct fastrouter_session *alloc_fr_session() {
return uwsgi_malloc(sizeof(struct fastrouter_session));
}
void fastrouter_loop() {
int fr_queue;
int fr_server = -1;
int nevents;
int interesting_fd;
int new_connection;
ssize_t len;
int i;
time_t delta;
char bbuf[UMAX16];
char *tcp_port;
char *tmp_socket_name;
int tmp_socket_name_len;
struct uwsgi_subscribe_req usr;
char *magic_table[0xff];
struct uwsgi_rb_timer *min_timeout;
void *events;
struct msghdr msg;
union {
struct cmsghdr cmsg;
char control [CMSG_SPACE (sizeof (int))];
} msg_control;
struct cmsghdr *cmsg;
struct sockaddr_un fr_addr;
socklen_t fr_addr_len = sizeof(struct sockaddr_un);
struct fastrouter_session *fr_session;
struct fastrouter_session *fr_table[2048];
struct iovec iov[2];
int soopt;
socklen_t solen = sizeof(int);
int ufr_subserver = -1;
for(i=0;i<2048;i++) {
fr_table[i] = NULL;
}
if (ufr.socket_name[0] == '=') {
int shared_socket = atoi(ufr.socket_name+1);
if (shared_socket >= 0 && shared_socket < uwsgi.shared_sockets_cnt) {
if (uwsgi.shared_sockets[shared_socket].name) {
fr_server = uwsgi.shared_sockets[shared_socket].fd;
}
else {
uwsgi_log("unable to use shared socket %d\n", shared_socket);
}
}
}
else {
tcp_port = strchr(ufr.socket_name, ':');
if (tcp_port) {
fr_server = bind_to_tcp(ufr.socket_name, uwsgi.listen_queue, tcp_port);
}
else {
fr_server = bind_to_unix(ufr.socket_name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
}
fr_queue = event_queue_init();
events = event_queue_alloc(ufr.nevents);
event_queue_add_fd_read(fr_queue, fr_server);
if (ufr.subscription_server) {
ufr_subserver = bind_to_udp(ufr.subscription_server, 0, 0);
event_queue_add_fd_read(fr_queue, ufr_subserver);
ufr.subscription_dict = uwsgi_dict_create(30, 0);
}
if (ufr.pattern) {
init_magic_table(magic_table);
}
ufr.timeouts = uwsgi_init_rb_timer();
if (!ufr.socket_timeout) ufr.socket_timeout = 30;
for (;;) {
min_timeout = uwsgi_min_rb_timer(ufr.timeouts);
if (min_timeout == NULL ) {
delta = -1;
}
else {
delta = min_timeout->key - time(NULL);
if (delta <= 0) {
expire_timeouts(fr_table);
delta = 0;
}
}
nevents = event_queue_wait_multi(fr_queue, delta, events, ufr.nevents);
if (nevents == 0) {
expire_timeouts(fr_table);
}
for (i=0;i<nevents;i++) {
tmp_socket_name = NULL;
interesting_fd = event_queue_interesting_fd(events, i);
if (interesting_fd == fr_server) {
new_connection = accept(fr_server, (struct sockaddr *) &fr_addr, &fr_addr_len);
if (new_connection < 0) {
continue;
}
fr_table[new_connection] = alloc_fr_session();
fr_table[new_connection]->fd = new_connection;
fr_table[new_connection]->instance_fd = -1;
fr_table[new_connection]->status = FASTROUTER_STATUS_RECV_HDR;
fr_table[new_connection]->h_pos = 0;
fr_table[new_connection]->pos = 0;
fr_table[new_connection]->instance_failed = 0;
fr_table[new_connection]->instance_address_len = 0;
fr_table[new_connection]->timeout = add_timeout(fr_table[new_connection]);
event_queue_add_fd_read(fr_queue, new_connection);
}
else if (interesting_fd == ufr_subserver) {
len = recv(ufr_subserver, bbuf, 4096, 0);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(fr_queue, ufr_subserver);
#endif
if (len > 0) {
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
uwsgi_hooked_parse(bbuf+4, len-4, fastrouter_manage_subscription, &usr);
uwsgi_add_subscriber(ufr.subscription_dict, usr.key, usr.keylen, usr.address, usr.address_len);
}
}
else {
fr_session = fr_table[interesting_fd];
// something is going wrong...
if (fr_session == NULL) continue;
if (event_queue_interesting_fd_has_error(events, i)) {
close_session(fr_table, fr_session);
continue;
}
fr_session->timeout = reset_timeout(fr_session);
switch(fr_session->status) {
case FASTROUTER_STATUS_RECV_HDR:
len = recv(fr_session->fd, (char *)(&fr_session->uh) + fr_session->h_pos, 4-fr_session->h_pos, 0);
if (len <= 0) {
uwsgi_error("recv()");
close_session(fr_table, fr_session);
break;
}
fr_session->h_pos += len;
if (fr_session->h_pos == 4) {
#ifdef UWSGI_DEBUG
uwsgi_log("modifier1: %d pktsize: %d modifier2: %d\n", fr_session->uh.modifier1, fr_session->uh.pktsize, fr_session->uh.modifier2);
#endif
fr_session->status = FASTROUTER_STATUS_RECV_VARS;
}
break;
case FASTROUTER_STATUS_RECV_VARS:
len = recv(fr_session->fd, fr_session->buffer + fr_session->pos, fr_session->uh.pktsize - fr_session->pos, 0);
if (len <= 0) {
uwsgi_error("recv()");
close_session(fr_table, fr_session);
break;
}
fr_session->pos += len;
if (fr_session->pos == fr_session->uh.pktsize) {
if (uwsgi_hooked_parse(fr_session->buffer, fr_session->uh.pktsize, fr_get_hostname, (void *) fr_session)) {
close_session(fr_table, fr_session);
break;
}
if (fr_session->hostname_len == 0) {
close_session(fr_table, fr_session);
break;
}
//uwsgi_log("requested domain %.*s\n", fr_session->hostname_len, fr_session->hostname);
if (ufr.use_cache) {
fr_session->instance_address = uwsgi_cache_get(fr_session->hostname, fr_session->hostname_len, &fr_session->instance_address_len);
}
else if (ufr.pattern) {
magic_table['s'] = uwsgi_concat2n(fr_session->hostname, fr_session->hostname_len, "", 0);
tmp_socket_name = magic_sub(ufr.pattern, ufr.pattern_len, &tmp_socket_name_len, magic_table);
free(magic_table['s']);
fr_session->instance_address_len = tmp_socket_name_len;
fr_session->instance_address = tmp_socket_name;
}
else if (ufr.subscription_server) {
fr_session->un = uwsgi_get_subscriber(ufr.subscription_dict, fr_session->hostname, fr_session->hostname_len);
if (fr_session->un && fr_session->un->len) {
fr_session->instance_address = fr_session->un->name;
fr_session->instance_address_len = fr_session->un->len;
}
}
else if (ufr.base) {
tmp_socket_name = uwsgi_concat2nn(ufr.base, ufr.base_len, fr_session->hostname, fr_session->hostname_len, &tmp_socket_name_len);
fr_session->instance_address_len = tmp_socket_name_len;
fr_session->instance_address = tmp_socket_name;
}
// no address found
if (!fr_session->instance_address_len) {
close_session(fr_table, fr_session);
break;
}
fr_session->pass_fd = is_unix(fr_session->instance_address, fr_session->instance_address_len);
fr_session->instance_fd = uwsgi_connectn(fr_session->instance_address, fr_session->instance_address_len, 0, 1);
if (tmp_socket_name) free(tmp_socket_name);
if (fr_session->instance_fd < 0) {
if (ufr.subscription_server) {
uwsgi_log("marking %.*s as failed\n", (int) fr_session->instance_address_len,fr_session->instance_address);
fr_session->un->len = 0;
}
close_session(fr_table, fr_session);
break;
}
fr_session->status = FASTROUTER_STATUS_CONNECTING;
fr_table[fr_session->instance_fd] = fr_session;
event_queue_add_fd_write(fr_queue, fr_session->instance_fd);
}
break;
case FASTROUTER_STATUS_CONNECTING:
if (interesting_fd == fr_session->instance_fd) {
if (getsockopt(fr_session->instance_fd, SOL_SOCKET, SO_ERROR, (void *) (&soopt), &solen) < 0) {
uwsgi_error("getsockopt()");
fr_session->instance_failed = 1;
close_session(fr_table, fr_session);
break;
}
if (soopt) {
uwsgi_log("unable to connect() to uwsgi instance: %s\n", strerror(soopt));
fr_session->instance_failed = 1;
close_session(fr_table, fr_session);
break;
}
iov[0].iov_base = &fr_session->uh;
iov[0].iov_len = 4;
iov[1].iov_base = fr_session->buffer;
iov[1].iov_len = fr_session->uh.pktsize;
// fd passing: PERFORMANCE EXTREME BOOST !!!
if (fr_session->pass_fd) {
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = iov;
msg.msg_iovlen = 2;
msg.msg_flags = 0;
msg.msg_control = &msg_control;
msg.msg_controllen = sizeof (msg_control);
cmsg = CMSG_FIRSTHDR (&msg);
cmsg->cmsg_len = CMSG_LEN (sizeof (int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
memcpy(CMSG_DATA(cmsg), &fr_session->fd, sizeof(int));
if (sendmsg(fr_session->instance_fd, &msg, 0) < 0) {
uwsgi_error("sendmsg()");
}
close_session(fr_table, fr_session);
break;
}
if (writev(fr_session->instance_fd, iov, 2) < 0) {
uwsgi_error("writev()");
close_session(fr_table, fr_session);
break;
}
event_queue_fd_write_to_read(fr_queue, fr_session->instance_fd);
fr_session->status = FASTROUTER_STATUS_RESPONSE;
}
break;
case FASTROUTER_STATUS_RESPONSE:
// data from instance
if (interesting_fd == fr_session->instance_fd) {
len = recv(fr_session->instance_fd, fr_session->buffer, 0xffff, 0);
if (len <= 0) {
if (len < 0) uwsgi_error("recv()");
close_session(fr_table, fr_session);
break;
}
len = send(fr_session->fd, fr_session->buffer, len, 0);
if (len <= 0) {
if (len < 0) uwsgi_error("send()");
close_session(fr_table, fr_session);
break;
}
}
// body from client
else if (interesting_fd == fr_session->fd) {
//uwsgi_log("receiving body...\n");
len = recv(fr_session->fd, fr_session->buffer, 0xffff, 0);
if (len <= 0) {
if (len < 0) uwsgi_error("recv()");
close_session(fr_table, fr_session);
break;
}
len = send(fr_session->instance_fd, fr_session->buffer, len, 0);
if (len <= 0) {
if (len < 0) uwsgi_error("send()");
close_session(fr_table, fr_session);
break;
}
}
break;
// fallback to destroy !!!
default:
uwsgi_log("default action\n");
close_session(fr_table, fr_session);
break;
}
}
}
}
}
int fastrouter_init() {
if (ufr.socket_name) {
if (ufr.use_cache && !uwsgi.cache_max_items) {
uwsgi_log("you need to create a uwsgi cache to use the fastrouter (add --cache <n>)\n");
exit(1);
}
if (!ufr.nevents) ufr.nevents = 64;
if (register_gateway("fastrouter", fastrouter_loop) == NULL) {
uwsgi_log("unable to register the fastrouter gateway\n");
exit(1);
}
}
return 0;
}
int fastrouter_opt(int i, char *optarg) {
switch(i) {
case LONG_ARGS_FASTROUTER:
ufr.socket_name = optarg;
return 1;
case LONG_ARGS_FASTROUTER_SUBSCRIPTION_SERVER:
ufr.subscription_server = optarg;
return 1;
case LONG_ARGS_FASTROUTER_EVENTS:
ufr.nevents = atoi(optarg);
return 1;
case LONG_ARGS_FASTROUTER_USE_PATTERN:
ufr.pattern = optarg;
// optimization
ufr.pattern_len = strlen(ufr.pattern);
return 1;
case LONG_ARGS_FASTROUTER_USE_BASE:
ufr.base = optarg;
// optimization
ufr.base_len = strlen(ufr.base);
return 1;
case LONG_ARGS_FASTROUTER_TIMEOUT:
ufr.socket_timeout = atoi(optarg);
return -1;
}
return 0;
}
struct uwsgi_plugin fastrouter_plugin = {
.name = "fastrouter",
.options = fastrouter_options,
.manage_opt = fastrouter_opt,
.init = fastrouter_init,
};
+7
View File
@@ -0,0 +1,7 @@
NAME='fastrouter'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['fastrouter']
+86
View File
@@ -0,0 +1,86 @@
#include "../python/uwsgi_python.h"
#include <greenlet/greenlet.h>
extern struct uwsgi_server uwsgi;
struct ugreenlet {
int enabled;
PyObject *callable;
PyGreenlet *main;
PyGreenlet **gl;
} ugl;
struct option greenlet_options[] = {
{"greenlet", no_argument, &ugl.enabled, 1},
{ 0, 0, 0, 0 }
};
PyObject *py_uwsgi_greenlet_request(PyObject * self, PyObject *args) {
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->request(uwsgi.wsgi_req);
uwsgi.wsgi_req->suspended = 0;
Py_DECREF(ugl.gl[uwsgi.wsgi_req->async_id]);
Py_INCREF(Py_None);
return Py_None;
}
PyMethodDef uwsgi_greenlet_request_method[] = {{"uwsgi_greenlet_request", py_uwsgi_greenlet_request, METH_VARARGS, ""}};
inline static void greenlet_schedule_to_req() {
int id = uwsgi.wsgi_req->async_id;
if (!uwsgi.wsgi_req->suspended) {
ugl.gl[id] = PyGreenlet_New(ugl.callable, NULL);
uwsgi.wsgi_req->suspended = 1;
}
PyGreenlet_Switch(ugl.gl[id], NULL, NULL);
if (uwsgi.wsgi_req->suspended) {
uwsgi.wsgi_req->async_status = UWSGI_AGAIN;
}
}
inline static void greenlet_schedule_to_main(struct wsgi_request *wsgi_req) {
PyGreenlet_Switch(ugl.main, NULL, NULL);
uwsgi.wsgi_req = wsgi_req;
}
int greenlet_init() {
return 0;
}
void greenlet_init_apps(void) {
if (!ugl.enabled) {
return;
}
PyGreenlet_Import();
ugl.gl = uwsgi_malloc( sizeof(PyGreenlet *) * uwsgi.async );
ugl.main = PyGreenlet_GetCurrent();
ugl.callable = PyCFunction_New(uwsgi_greenlet_request_method, NULL);
uwsgi_log("enabled greenlet engine\n");
uwsgi.schedule_to_main = greenlet_schedule_to_main;
uwsgi.schedule_to_req = greenlet_schedule_to_req;
return;
}
struct uwsgi_plugin greenlet_plugin = {
.name = "greenlet",
.init = greenlet_init,
.init_apps = greenlet_init_apps,
.options = greenlet_options,
};
+8
View File
@@ -0,0 +1,8 @@
from distutils import sysconfig
NAME='greenlet'
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True)]
LDFLAGS = []
LIBS = []
GCC_LIST = ['greenlet']
+950
View File
@@ -0,0 +1,950 @@
/*
uWSGI http
requires:
- async
- caching
- pcre (optional)
*/
#include "../../uwsgi.h"
#define MAX_HTTP_VEC 128
#define MAX_HTTP_EXTRA_VARS 64
#define LONG_ARGS_HTTP_EVENTS 300001
#define LONG_ARGS_HTTP_USE_PATTERN 300002
#define LONG_ARGS_HTTP_USE_BASE 300003
#define LONG_ARGS_HTTP_USE_TO 300004
#define LONG_ARGS_HTTP_SUBSCRIPTION_SERVER 300005
#define LONG_ARGS_HTTP_TIMEOUT 300006
#define HTTP_STATUS_FREE 0
#define HTTP_STATUS_CONNECTING 1
#define HTTP_STATUS_RECV 2
#define HTTP_STATUS_RESPONSE 4
#define add_timeout(x) uwsgi_add_rb_timer(uhttp.timeouts, time(NULL)+uhttp.socket_timeout, x)
#define del_timeout(x) rb_erase(&x->timeout->rbt, uhttp.timeouts); free(x->timeout);
struct uwsgi_http {
char *socket_name;
int use_cache;
int use_cluster;
int nevents;
int server;
char *subscription_server;
char *pattern;
int pattern_len;
char *base;
int base_len;
char *port;
int port_len;
char *to;
int to_len;
char *http_vars[MAX_HTTP_EXTRA_VARS];
int http_vars_cnt;
uint8_t modifier1;
int load;
int socket_timeout;
struct uwsgi_dict *subscription_dict;
struct rb_root *timeouts;
} uhttp;
struct option http_options[] = {
{"http", required_argument, 0, LONG_ARGS_HTTP},
{"http-var", required_argument, 0, LONG_ARGS_HTTP_VAR},
{"http-to", required_argument, 0, LONG_ARGS_HTTP_USE_TO},
{"http-modifier1", required_argument, 0, LONG_ARGS_HTTP_MODIFIER1},
{"http-use-cache", no_argument, &uhttp.use_cache, 1},
{"http-use-pattern", required_argument, 0, LONG_ARGS_HTTP_USE_PATTERN},
{"http-use-base", required_argument, 0, LONG_ARGS_HTTP_USE_BASE},
{"http-use-cluster", no_argument, &uhttp.use_cluster, 1},
{"http-events", required_argument, 0, LONG_ARGS_HTTP_EVENTS},
{"http-subscription-server", required_argument, 0, LONG_ARGS_HTTP_SUBSCRIPTION_SERVER},
{"http-timeout", required_argument, 0, LONG_ARGS_HTTP_TIMEOUT},
{0, 0, 0, 0},
};
extern struct uwsgi_server uwsgi;
void http_manage_subscription(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
struct uwsgi_subscribe_req *usr = (struct uwsgi_subscribe_req *) data;
if (!uwsgi_strncmp("key", 3, key, keylen)) {
usr->key = val;
usr->keylen = vallen;
}
else if (!uwsgi_strncmp("auth", 4, key, keylen)) {
usr->auth = val;
usr->auth_len = vallen;
}
else if (!uwsgi_strncmp("address", 7, key, keylen)) {
usr->address = val;
usr->address_len = vallen;
}
}
struct http_session {
int fd;
int instance_fd;
int status;
struct uwsgi_header uh;
uint8_t h_pos;
uint16_t pos;
uint16_t parse_pos;
char *ptr;
int rnrn;
char *hostname;
uint16_t hostname_len;
char *instance_address;
uint64_t instance_address_len;
int instance_failed;
int pass_fd;
int remains;
struct iovec iov[MAX_HTTP_VEC];
int iov_len;
char uss[MAX_HTTP_VEC*2];
char buffer[UMAX16];
struct uwsgi_subscriber_name *un;
in_addr_t ip_addr;
char ip[INET_ADDRSTRLEN];
struct uwsgi_rb_timer *timeout;
};
static struct uwsgi_rb_timer *reset_timeout(struct http_session *uhttp_session) {
del_timeout(uhttp_session);
return add_timeout(uhttp_session);
}
static void close_session(struct http_session **uhttp_table, struct http_session *uhttp_session) {
close(uhttp_session->fd);
uhttp_table[uhttp_session->fd] = NULL;
if (uhttp_session->instance_fd != -1) {
if (uhttp.subscription_server && (uhttp_session->instance_failed || uhttp_session->status == HTTP_STATUS_CONNECTING)) {
uwsgi_log("marking %.*s as failed\n", (int) uhttp_session->instance_address_len,uhttp_session->instance_address);
uhttp_session->un->len = 0;
}
close(uhttp_session->instance_fd);
uhttp_table[uhttp_session->instance_fd] = NULL;
}
uhttp.load--;
del_timeout(uhttp_session);
free(uhttp_session);
}
static void expire_timeouts(struct http_session **uhttp_table) {
time_t current = time(NULL);
struct uwsgi_rb_timer *urbt;
for(;;) {
urbt = uwsgi_min_rb_timer(uhttp.timeouts);
if (urbt == NULL) return;
if (urbt->key <= current) {
close_session(uhttp_table, (struct http_session *)urbt->data);
uwsgi_log("timeout !!!\n");
continue;
}
break;
}
}
struct http_session *alloc_uhttp_session() {
return uwsgi_malloc(sizeof(struct http_session));
}
uint16_t http_add_uwsgi_header(struct http_session *h_session, struct iovec *iov, char *strsize1, char *strsize2, char *hh, uint16_t hhlen, int *c) {
int i;
int status = 0;
char *val = hh;
uint16_t keylen = 0, vallen = 0;
int prefix = 0;
if (*c >= MAX_HTTP_VEC) return 0;
for(i=0;i<hhlen;i++) {
if (!status) {
hh[i] = toupper((int)hh[i]);
if (hh[i] == '-') hh[i] = '_';
if (hh[i] == ':') {
status = 1;
keylen = i;
}
}
else if (status == 1 && hh[i] != ' ') {
status = 2;
val += i;
vallen++;
}
else if (status == 2) {
vallen++;
}
}
if (!keylen) return 0;
if ((*c) + 4 >= MAX_HTTP_VEC) return 0;
if (!uwsgi_strncmp("HOST", 4, hh, keylen)) {
h_session->hostname = val;
h_session->hostname_len = vallen;
}
if (uwsgi_strncmp("CONTENT_TYPE", 12, hh, keylen) && uwsgi_strncmp("CONTENT_LENGTH", 14, hh, keylen)) {
keylen += 5;
prefix = 1;
if ((*c) + 5 >= MAX_HTTP_VEC) return 0;
}
strsize1[0] = (uint8_t) (keylen & 0xff);
strsize1[1] = (uint8_t) ((keylen >> 8) & 0xff);
iov[*c].iov_base = strsize1 ;
iov[*c].iov_len = 2 ;
*c+=1;
if (prefix) {
iov[*c].iov_base = "HTTP_" ;
iov[*c].iov_len = 5 ;
*c+=1;
}
iov[*c].iov_base = hh ;
iov[*c].iov_len = keylen - (prefix*5) ;
*c+=1;
strsize2[0] = (uint8_t) (vallen & 0xff);
strsize2[1] = (uint8_t) ((vallen >> 8) & 0xff);
iov[*c].iov_base = strsize2 ;
iov[*c].iov_len = 2 ;
*c+=1;
iov[*c].iov_base = val ;
iov[*c].iov_len = vallen ;
*c+=1;
return 2+keylen+2+vallen;
}
uint16_t http_add_uwsgi_var(struct iovec *iov, char *strsize1, char *strsize2, char *key, uint16_t keylen, char *val, uint16_t vallen, int *c) {
if ((*c) + 4 >= MAX_HTTP_VEC) return 0;
strsize1[0] = (uint8_t) (keylen & 0xff);
strsize1[1] = (uint8_t) ((keylen >> 8) & 0xff);
iov[*c].iov_base = strsize1 ;
iov[*c].iov_len = 2 ;
*c+=1;
iov[*c].iov_base = key ;
iov[*c].iov_len = keylen ;
*c+=1;
strsize2[0] = (uint8_t) (vallen & 0xff);
strsize2[1] = (uint8_t) ((vallen >> 8) & 0xff);
iov[*c].iov_base = strsize2 ;
iov[*c].iov_len = 2 ;
*c+=1;
iov[*c].iov_base = val ;
iov[*c].iov_len = vallen ;
*c+=1;
return 2+keylen+2+vallen;
}
int http_parse(struct http_session *h_session) {
char *ptr = h_session->buffer;
char *watermark = h_session->ptr;
char *base = ptr;
// leave a slot for uwsgi header
int c = 1;
char *query_string = NULL;
// REQUEST_METHOD
while(ptr < watermark) {
if (*ptr == ' ') {
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "REQUEST_METHOD", 14, base, ptr-base, &c);
ptr++;
break;
}
ptr++;
}
// REQUEST_URI / PATH_INFO / QUERY_STRING
base = ptr;
while(ptr < watermark) {
if (*ptr == '?' && !query_string) {
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "PATH_INFO", 9, base, ptr-base, &c);
query_string = ptr+1;
}
else if (*ptr == ' ') {
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "REQUEST_URI", 11, base, ptr-base, &c);
if (!query_string) {
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "PATH_INFO", 9, base, ptr-base, &c);
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "QUERY_STRING", 12, "", 0, &c);
}
else {
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "QUERY_STRING", 12, query_string, ptr-query_string, &c);
}
ptr++;
break;
}
ptr++;
}
// SERVER_PROTOCOL
base = ptr;
while(ptr < watermark) {
if (*ptr == '\r') {
if (ptr + 1 >= watermark) return 0;
if (*(ptr+1) != '\n') return 0;
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "SERVER_PROTOCOL", 15, base, ptr-base, &c);
ptr+=2;
break;
}
ptr++;
}
// SCRIPT_NAME
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "SCRIPT_NAME", 11, "", 0, &c);
// SERVER_NAME
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "SERVER_NAME", 11, uwsgi.hostname, uwsgi.hostname_len, &c);
h_session->hostname = uwsgi.hostname;
h_session->hostname_len = uwsgi.hostname_len;
// SERVER_PORT
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "SERVER_PORT", 11, uhttp.port, uhttp.port_len, &c);
h_session->hostname = uwsgi.hostname;
h_session->hostname_len = uwsgi.hostname_len;
// UWSGI_ROUTER
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "UWSGI_ROUTER", 12, "http", 4, &c);
// REMOTE_ADDR
if (inet_ntop(AF_INET, &h_session->ip_addr, h_session->ip, INET_ADDRSTRLEN)) {
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "REMOTE_ADDR", 11, h_session->ip, strlen(h_session->ip), &c);
}
else {
uwsgi_error("inet_ntop()");
}
//HEADERS
base = ptr;
while(ptr < watermark) {
if (*ptr == '\r') {
if (ptr + 1 >= watermark) return 0;
if (*(ptr+1) != '\n') return 0;
// multiline header ?
if (ptr+2 < watermark) {
if (*(ptr+2) == ' ' || *(ptr+2) == '\t') {
ptr+=2;
continue;
}
}
h_session->uh.pktsize += http_add_uwsgi_header(h_session, h_session->iov, h_session->uss+c, h_session->uss+c+2, base, ptr-base, &c);
ptr++;
base = ptr+1;
}
ptr++;
}
#ifdef UWSGI_DEBUG
uwsgi_log("vec size: %d pkt size: %d load %d\n", c, h_session->uh.pktsize, uhttp.load);
#endif
return c;
}
void http_loop() {
int uhttp_queue;
int uhttp_subserver = -1;
int nevents;
int interesting_fd;
int new_connection;
ssize_t len;
int i,j;
char *magic_table[0xff];
char bbuf[UMAX16];
time_t delta;
struct uwsgi_rb_timer *min_timeout;
void *events;
#ifndef __sun__
struct msghdr msg;
union {
struct cmsghdr cmsg;
char control [CMSG_SPACE (sizeof (int))];
} msg_control;
struct cmsghdr *cmsg;
#endif
union uwsgi_sockaddr uhttp_addr;
socklen_t uhttp_addr_len = sizeof(struct sockaddr_un);
struct http_session *uhttp_session;
struct http_session *uhttp_table[2048];
struct uwsgi_subscribe_req usr;
int soopt;
socklen_t solen = sizeof(int);
for(i=0;i<2048;i++) {
uhttp_table[i] = NULL;
}
uhttp.port = strchr(uhttp.socket_name,':')+1;
uhttp.port_len = strlen(uhttp.port);
uhttp_queue = event_queue_init();
events = event_queue_alloc(uhttp.nevents);
event_queue_add_fd_read(uhttp_queue, uhttp.server);
if (uhttp.subscription_server) {
uhttp_subserver = bind_to_udp(uhttp.subscription_server, 0, 0);
event_queue_add_fd_read(uhttp_queue, uhttp_subserver);
uhttp.subscription_dict = uwsgi_dict_create(100, 0);
}
if (uhttp.pattern) {
init_magic_table(magic_table);
}
uhttp.timeouts = uwsgi_init_rb_timer();
if (!uhttp.socket_timeout) uhttp.socket_timeout = 30;
for (;;) {
min_timeout = uwsgi_min_rb_timer(uhttp.timeouts);
if (min_timeout == NULL ) {
delta = -1;
}
else {
delta = min_timeout->key - time(NULL);
if (delta <= 0) {
expire_timeouts(uhttp_table);
delta = 0;
}
}
nevents = event_queue_wait_multi(uhttp_queue, delta, events, uhttp.nevents);
if (nevents == 0) {
// manage timeout
expire_timeouts(uhttp_table);
}
for (i=0;i<nevents;i++) {
interesting_fd = event_queue_interesting_fd(events, i);
if (interesting_fd == uhttp.server) {
new_connection = accept(uhttp.server, (struct sockaddr *) &uhttp_addr, &uhttp_addr_len);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(uhttp_queue, uhttp.server);
#endif
if (new_connection < 0) {
continue;
}
uhttp_table[new_connection] = alloc_uhttp_session();
uhttp_table[new_connection]->fd = new_connection;
uhttp_table[new_connection]->instance_fd = -1;
uhttp_table[new_connection]->status = HTTP_STATUS_RECV;
uhttp_table[new_connection]->h_pos = 0;
uhttp_table[new_connection]->pos = 0;
uhttp_table[new_connection]->rnrn = 0;
uhttp_table[new_connection]->parse_pos = 0;
uhttp_table[new_connection]->pass_fd = 0;
uhttp_table[new_connection]->ptr = uhttp_table[new_connection]->buffer;
uhttp_table[new_connection]->instance_address_len = 0;
uhttp_table[new_connection]->uh.modifier1 = uhttp.modifier1;
uhttp_table[new_connection]->uh.pktsize = 0;
uhttp_table[new_connection]->uh.modifier2 = 0;
uhttp_table[new_connection]->ip_addr = ((struct sockaddr_in *) &uhttp_addr)->sin_addr.s_addr;
uhttp_table[new_connection]->instance_failed = 0;
uhttp_table[new_connection]->timeout = add_timeout(uhttp_table[new_connection]);
uhttp.load++;
event_queue_add_fd_read(uhttp_queue, new_connection);
}
else if (interesting_fd == uhttp_subserver) {
len = recv(uhttp_subserver, bbuf, 4096, 0);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(uhttp_queue, uhttp_subserver);
#endif
if (len > 0) {
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
uwsgi_hooked_parse(bbuf+4, len-4, http_manage_subscription, &usr);
uwsgi_add_subscriber(uhttp.subscription_dict, usr.key, usr.keylen, usr.address, usr.address_len);
}
}
else {
uhttp_session = uhttp_table[interesting_fd];
// something is going wrong...
if (uhttp_session == NULL) continue;
if (event_queue_interesting_fd_has_error(events, i)) {
close_session(uhttp_table, uhttp_session);
continue;
}
uhttp_session->timeout = reset_timeout(uhttp_session);
switch(uhttp_session->status) {
case HTTP_STATUS_RECV:
len = recv(uhttp_session->fd, uhttp_session->buffer + uhttp_session->h_pos, UMAX16-uhttp_session->h_pos, 0);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(uhttp_queue, uhttp_session->fd);
#endif
if (len <= 0) {
uwsgi_error("recv()");
close_session(uhttp_table, uhttp_session);
break;
}
uhttp_session->h_pos += len;
for(j=0;j<len;j++) {
//uwsgi_log("%d %d %d\n", j, *uhttp_session->ptr, uhttp_session->rnrn);
if (*uhttp_session->ptr == '\r' && (uhttp_session->rnrn == 0 || uhttp_session->rnrn == 2)) {
uhttp_session->rnrn++;
}
else if (*uhttp_session->ptr == '\r') {
uhttp_session->rnrn = 1;
}
else if (*uhttp_session->ptr == '\n' && uhttp_session->rnrn == 1) {
uhttp_session->rnrn = 2;
}
else if (*uhttp_session->ptr == '\n' && uhttp_session->rnrn == 3) {
uhttp_session->ptr++;
uhttp_session->remains = len-(j+1);
uhttp_session->iov_len = http_parse(uhttp_session);
if (uhttp_session->iov_len == 0) {
close_session(uhttp_table, uhttp_session);
break;
}
if (uhttp.use_cluster) {
uhttp_session->instance_address = uwsgi_cluster_best_node();
if (uhttp_session->instance_address) {
uhttp_session->instance_address_len = strlen(uhttp_session->instance_address);
}
}
else if (uhttp.use_cache) {
uhttp_session->instance_address = uwsgi_cache_get(uhttp_session->hostname, uhttp_session->hostname_len, &uhttp_session->instance_address_len);
}
else if (uhttp.base) {
uhttp_session->instance_address = uwsgi_concat2n(uhttp.base, uhttp.base_len, uhttp_session->hostname, uhttp_session->hostname_len);
uhttp_session->instance_address_len = uhttp.base_len + uhttp_session->hostname_len;
}
else if (uhttp.pattern) {
magic_table['s'] = uwsgi_concat2n(uhttp_session->hostname, uhttp_session->hostname_len, "", 0);
int tmp_addr_len = 0;
uhttp_session->instance_address = magic_sub(uhttp.pattern, uhttp.pattern_len, &tmp_addr_len, magic_table);
uhttp_session->instance_address_len = tmp_addr_len;
free(magic_table['s']);
}
else if (uhttp.to) {
uhttp_session->instance_address = uhttp.to;
uhttp_session->instance_address_len = uhttp.to_len;
}
else if (uhttp.subscription_server) {
uhttp_session->un = uwsgi_get_subscriber(uhttp.subscription_dict, uhttp_session->hostname, uhttp_session->hostname_len);
if (uhttp_session->un && uhttp_session->un->len) {
uhttp_session->instance_address = uhttp_session->un->name;
uhttp_session->instance_address_len = uhttp_session->un->len;
}
}
else if (uwsgi.sockets_cnt > 0) {
uhttp_session->instance_address = uwsgi.sockets[0].name;
uhttp_session->instance_address_len = strlen(uwsgi.sockets[0].name);
}
if (!uhttp_session->instance_address_len) {
close_session(uhttp_table, uhttp_session);
break;
}
uhttp_session->pass_fd = is_unix(uhttp_session->instance_address, uhttp_session->instance_address_len);
uhttp_session->instance_fd = uwsgi_connectn(uhttp_session->instance_address, uhttp_session->instance_address_len, 0, 1);
#ifdef UWSGI_DEBUG
uwsgi_log("uwsgi backend: %.*s\n", (int) uhttp_session->instance_address_len,uhttp_session->instance_address);
#endif
if (uhttp.pattern || uhttp.base ) {
free(uhttp_session->instance_address);
}
if (uhttp_session->instance_fd < 0) {
if (uhttp.subscription_server) {
uwsgi_log("marking %.*s as failed\n", (int) uhttp_session->instance_address_len,uhttp_session->instance_address);
uhttp_session->un->len = 0;
}
close_session(uhttp_table, uhttp_session);
break;
}
uhttp_session->status = HTTP_STATUS_CONNECTING;
uhttp_table[uhttp_session->instance_fd] = uhttp_session;
event_queue_add_fd_write(uhttp_queue, uhttp_session->instance_fd);
break;
}
else {
uhttp_session->rnrn = 0;
}
uhttp_session->ptr++;
}
break;
case HTTP_STATUS_CONNECTING:
if (interesting_fd == uhttp_session->instance_fd) {
if (getsockopt(uhttp_session->instance_fd, SOL_SOCKET, SO_ERROR, (void *) (&soopt), &solen) < 0) {
uwsgi_error("getsockopt()");
uhttp_session->instance_failed = 1;
close_session(uhttp_table, uhttp_session);
break;
}
if (soopt) {
uwsgi_log("unable to connect() to uwsgi instance: %s\n", strerror(soopt));
uhttp_session->instance_failed = 1;
close_session(uhttp_table, uhttp_session);
break;
}
#ifdef __BIG_ENDIAN__
uhttp_session->uh.pktsize = uwsgi_swap16(uhttp_session->uh.pktsize);
#endif
uhttp_session->iov[0].iov_base = &uhttp_session->uh;
uhttp_session->iov[0].iov_len = 4;
if (uhttp_session->remains > 0) {
uhttp_session->iov[uhttp_session->iov_len].iov_base = uhttp_session->ptr;
uhttp_session->iov[uhttp_session->iov_len].iov_len = uhttp_session->remains;
uhttp_session->iov_len++;
}
#ifndef __sun__
// fd passing: PERFORMANCE EXTREME BOOST !!!
if (uhttp_session->pass_fd && !uhttp_session->remains) {
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = uhttp_session->iov;
msg.msg_iovlen = uhttp_session->iov_len;
msg.msg_flags = 0;
msg.msg_control = &msg_control;
msg.msg_controllen = sizeof (msg_control);
cmsg = CMSG_FIRSTHDR (&msg);
cmsg->cmsg_len = CMSG_LEN (sizeof (int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
memcpy(CMSG_DATA(cmsg), &uhttp_session->fd, sizeof(int));
if (sendmsg(uhttp_session->instance_fd, &msg, 0) < 0) {
uwsgi_error("sendmsg()");
}
close(uhttp_session->fd);
close(uhttp_session->instance_fd);
uhttp_table[uhttp_session->fd] = NULL;
uhttp_table[uhttp_session->instance_fd] = NULL;
uhttp.load--;
del_timeout(uhttp_session);
free(uhttp_session);
break;
}
#endif
#ifdef __sun__
if (uhttp_session->iov_len > IOV_MAX) {
int remains = uhttp_session->iov_len;
int iov_len;
while(remains) {
if (remains > IOV_MAX) {
iov_len = IOV_MAX;
}
else {
iov_len = remains;
}
if (writev(uhttp_session->instance_fd, uhttp_session->iov + (uhttp_session->iov_len-remains), iov_len) <= 0) {
uwsgi_error("writev()");
close_session(uhttp_table, uhttp_session);
break;
}
remains -= iov_len;
}
}
#else
if (writev(uhttp_session->instance_fd, uhttp_session->iov, uhttp_session->iov_len) <= 0) {
uwsgi_error("writev()");
close_session(uhttp_table, uhttp_session);
break;
}
#endif
event_queue_fd_write_to_read(uhttp_queue, uhttp_session->instance_fd);
uhttp_session->status = HTTP_STATUS_RESPONSE;
}
break;
case HTTP_STATUS_RESPONSE:
// data from instance
if (interesting_fd == uhttp_session->instance_fd) {
len = recv(uhttp_session->instance_fd, bbuf, UMAX16, 0);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(uhttp_queue, uhttp_session->instance_fd);
#endif
if (len <= 0) {
if (len < 0) uwsgi_error("recv()");
close_session(uhttp_table, uhttp_session);
break;
}
len = send(uhttp_session->fd, bbuf, len, 0);
if (len <= 0) {
if (len < 0) uwsgi_error("send()");
close(uhttp_session->fd);
close(uhttp_session->instance_fd);
uhttp_table[uhttp_session->fd] = NULL;
uhttp_table[uhttp_session->instance_fd] = NULL;
uhttp.load--;
del_timeout(uhttp_session);
free(uhttp_session);
break;
}
}
// body from client
else if (interesting_fd == uhttp_session->fd) {
//uwsgi_log("receiving body...\n");
len = recv(uhttp_session->fd, bbuf, UMAX16, 0);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(uhttp_queue, uhttp_session->fd);
#endif
if (len <= 0) {
if (len < 0) uwsgi_error("recv()");
close(uhttp_session->fd);
close(uhttp_session->instance_fd);
uhttp_table[uhttp_session->fd] = NULL;
uhttp_table[uhttp_session->instance_fd] = NULL;
uhttp.load--;
del_timeout(uhttp_session);
free(uhttp_session);
break;
}
len = send(uhttp_session->instance_fd, bbuf, len, 0);
if (len <= 0) {
if (len < 0) uwsgi_error("send()");
close_session(uhttp_table, uhttp_session);
break;
}
}
break;
// fallback to destroy !!!
default:
uwsgi_log("default action\n");
close(uhttp_session->fd);
uhttp_table[uhttp_session->fd] = NULL;
if (uhttp_session->instance_fd != -1) {
close(uhttp_session->instance_fd);
uhttp_table[uhttp_session->instance_fd] = NULL;
}
uhttp.load--;
del_timeout(uhttp_session);
free(uhttp_session);
break;
}
}
}
}
}
int http_init() {
if (uhttp.socket_name) {
if (uhttp.use_cache && !uwsgi.cache_max_items) {
uwsgi_log("you need to create a uwsgi cache to use the http (add --cache <n>)\n");
exit(1);
}
if (!uhttp.nevents) uhttp.nevents = 64;
if (!uhttp.base && !uhttp.use_cache && !uhttp.to && !uwsgi.sockets_cnt && !uhttp.subscription_server && !uhttp.use_cluster) {
uwsgi.sockets[0].name = uwsgi_malloc(64);
uwsgi.sockets_cnt++;
snprintf(uwsgi.sockets[0].name, 64, "%d_%d.sock", (int) time(NULL), (int) getpid());
}
uhttp.server = bind_to_tcp(uhttp.socket_name, uwsgi.listen_queue, strchr(uhttp.socket_name,':'));
if (register_gateway("http", http_loop) == NULL) {
uwsgi_log("unable to register the http gateway\n");
exit(1);
}
uwsgi_log("HTTP router/proxy bound on %s\n", uhttp.socket_name);
}
return 0;
}
struct uwsgi_help_item http_help[] = {
{ "http-to <addr>", "forward http requests to uwsgi instance bound at <addr>"},
{ 0, 0 }
};
int http_opt(int i, char *optarg) {
switch(i) {
case LONG_ARGS_HTTP:
uhttp.socket_name = optarg;
return 1;
case LONG_ARGS_HTTP_SUBSCRIPTION_SERVER:
uhttp.subscription_server = optarg;
return 1;
case LONG_ARGS_HTTP_EVENTS:
uhttp.nevents = atoi(optarg);
return 1;
case LONG_ARGS_HTTP_USE_PATTERN:
uhttp.pattern = optarg;
// optimization
uhttp.pattern_len = strlen(uhttp.pattern);
return 1;
case LONG_ARGS_HTTP_USE_BASE:
uhttp.base = optarg;
// optimization
uhttp.base_len = strlen(uhttp.base);
return 1;
case LONG_ARGS_HTTP_USE_TO:
uhttp.to = optarg;
// optimization
uhttp.to_len = strlen(uhttp.to);
return 1;
case LONG_ARGS_HTTP_VAR:
if (uhttp.http_vars_cnt < MAX_HTTP_EXTRA_VARS) {
uhttp.http_vars[uhttp.http_vars_cnt] = optarg;
uhttp.http_vars_cnt++;
} else {
uwsgi_log("you can specify at most 64 --http-var options\n");
}
return 1;
case LONG_ARGS_HTTP_MODIFIER1:
uhttp.modifier1 = (uint8_t) atoi(optarg);
return 1;
case LONG_ARGS_HTTP_TIMEOUT:
uhttp.socket_timeout = atoi(optarg);
return 1;
}
return 0;
}
struct uwsgi_plugin http_plugin = {
.name = "http",
.options = http_options,
.manage_opt = http_opt,
.help = http_help,
.init = http_init,
};
+7
View File
@@ -0,0 +1,7 @@
NAME='http'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['http']
+41
View File
@@ -0,0 +1,41 @@
#include "../../uwsgi.h"
#include <jni.h>
#define MAX_CLASSPATH 64
#define LONG_ARGS_JVM_BASE 17000 + (300 * 100)
#define LONG_ARGS_JVM_CLASS LONG_ARGS_JVM_BASE + 1
#define LONG_ARGS_JVM_CLASSPATH LONG_ARGS_JVM_BASE + 2
struct uwsgi_jvm {
char *classpath[MAX_CLASSPATH];
int classpath_cnt;
JNIEnv *env;
char *class;
jclass main_class;
jclass str_class;
jclass ht_class;
jclass fd_class;
};
jmethodID uwsgi_jvm_get_method_id(jclass, char *, char *);
jmethodID uwsgi_jvm_get_static_method_id(jclass, char *, char *);
jclass uwsgi_jvm_get_class(char *);
jclass uwsgi_jvm_get_object_class(jobject);
int uwsgi_jvm_exception(void);
jobject uwsgi_jvm_str_new(char *, int );
jobject uwsgi_jvm_str(char *);
jobject uwsgi_jvm_array_get(jobject , int );
jobject uwsgi_jvm_ht_new(void);
jobject uwsgi_jvm_ht_put(jobject, jobject, jobject);
jobject uwsgi_jvm_fd(int);
char *uwsgi_jvm_str2c(jobject);
int uwsgi_jvm_strlen2c(jobject);
+230
View File
@@ -0,0 +1,230 @@
#include "jvm.h"
/*
with javap -s -p <class>
you can get method signatures
*/
struct uwsgi_jvm ujvm;
struct option uwsgi_jvm_options[] = {
{"jvm-main-class", required_argument, 0, LONG_ARGS_JVM_CLASS},
{"jvm-classpath", required_argument, 0, LONG_ARGS_JVM_CLASSPATH},
{0, 0, 0, 0},
};
int uwsgi_jvm_exception(void) {
if ((*ujvm.env)->ExceptionOccurred(ujvm.env)) {
(*ujvm.env)->ExceptionDescribe(ujvm.env);
(*ujvm.env)->ExceptionClear(ujvm.env);
return 1;
}
return 0;
}
jclass uwsgi_jvm_get_object_class(jobject obj) {
return (*ujvm.env)->GetObjectClass(ujvm.env, obj);
}
jclass uwsgi_jvm_get_class(char *name) {
jclass my_class = (*ujvm.env)->FindClass(ujvm.env, name);
if (uwsgi_jvm_exception()) {
return NULL;
}
return my_class;
}
jmethodID uwsgi_jvm_get_method_id(jclass cls, char *name, char *signature) {
jmethodID mid;
mid = (*ujvm.env)->GetMethodID(ujvm.env, cls, name, signature);
return mid;
}
jmethodID uwsgi_jvm_get_static_method_id(jclass cls, char *name, char *signature) {
jmethodID mid;
mid = (*ujvm.env)->GetStaticMethodID(ujvm.env, cls, name, signature);
return mid;
}
jobject uwsgi_jvm_str_new(char *str, int len) {
jbyteArray ba;
static jmethodID str_new_mid = 0;
if (!str_new_mid) {
str_new_mid = uwsgi_jvm_get_method_id(ujvm.str_class, "<init>", "([BLjava/lang/String;)V");
}
ba = (*ujvm.env)->NewByteArray(ujvm.env, len);
(*ujvm.env)->SetByteArrayRegion(ujvm.env, ba, 0, len, (jbyte *) str);
return (*ujvm.env)->NewObject(ujvm.env, ujvm.str_class, str_new_mid, ba,
(*ujvm.env)->NewStringUTF(ujvm.env, "UTF-8"));
}
jobject uwsgi_jvm_str(char *str) {
return (*ujvm.env)->NewStringUTF(ujvm.env, str);
}
int jvm_init(void) {
jint res;
JavaVM *jvm;
JavaVMInitArgs vm_args;
JavaVMOption options[1];
jmethodID mmid;
int i;
char *old_cp = NULL ;
vm_args.version = JNI_VERSION_1_2;
JNI_GetDefaultJavaVMInitArgs(&vm_args);
options[0].optionString = "-Djava.class.path=.";
if (ujvm.classpath_cnt > 0) {
for(i=0;i<ujvm.classpath_cnt;i++) {
if (old_cp) {
options[0].optionString = uwsgi_concat3(old_cp, ":", ujvm.classpath[i]);
free(old_cp);
}
else {
options[0].optionString = uwsgi_concat3(options[0].optionString, ":", ujvm.classpath[i]);
}
old_cp = options[0].optionString ;
}
}
vm_args.options = options;
vm_args.nOptions = 1;
res = JNI_CreateJavaVM(&jvm, (void **) &ujvm.env, &vm_args);
if (res) {
uwsgi_log("unable to initialize JVM\n");
exit(1);
}
uwsgi_log("JVM initialized\n");
if (ujvm.class) {
ujvm.main_class = uwsgi_jvm_get_class(ujvm.class);
if (!ujvm.main_class) {
exit(1);
}
mmid = uwsgi_jvm_get_static_method_id(ujvm.main_class, "main", "([Ljava/lang/String;)V");
if (mmid) {
(*ujvm.env)->CallStaticVoidMethod(ujvm.env, ujvm.main_class, mmid);
uwsgi_jvm_exception();
}
}
ujvm.str_class = uwsgi_jvm_get_class("java/lang/String");
ujvm.ht_class = uwsgi_jvm_get_class("java/util/Hashtable");
ujvm.fd_class = uwsgi_jvm_get_class("java/io/FileDescriptor");
return 1;
}
jobject uwsgi_jvm_array_get(jobject obj, int index) {
return (*ujvm.env)->GetObjectArrayElement(ujvm.env, obj, index);
}
jobject uwsgi_jvm_ht_new() {
static jmethodID htimid = 0;
if (!htimid) {
htimid = uwsgi_jvm_get_method_id(ujvm.ht_class, "<init>", "()V");
}
return (*ujvm.env)->NewObject(ujvm.env, ujvm.ht_class, htimid);
}
jobject uwsgi_jvm_ht_put(jobject obj, jobject key, jobject val) {
static jmethodID htpmid = 0 ;
if (!htpmid) {
htpmid = uwsgi_jvm_get_method_id(ujvm.ht_class, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
}
return (*ujvm.env)->CallObjectMethod(ujvm.env, obj, htpmid, key, val);
}
jobject uwsgi_jvm_fd(int fd) {
jobject fd_obj;
static jmethodID fd_mid = 0;
static jfieldID fd_field = 0 ;
if (!fd_mid) {
fd_mid = uwsgi_jvm_get_method_id( ujvm.fd_class, "<init>", "()V");
}
fd_obj = (*ujvm.env)->NewObject(ujvm.env, ujvm.fd_class, fd_mid);
if (!fd_field) {
fd_field = (*ujvm.env)->GetFieldID(ujvm.env, ujvm.fd_class, "fd", "I");
}
(*ujvm.env)->SetIntField(ujvm.env, fd_obj, fd_field, fd);
return fd_obj;
}
char *uwsgi_jvm_str2c(jobject obj) {
return (char *) (*ujvm.env)->GetStringUTFChars(ujvm.env, obj, NULL);
}
int uwsgi_jvm_strlen2c(jobject obj) {
return (*ujvm.env)->GetStringUTFLength(ujvm.env, obj);
}
int uwsgi_jvm_manage_opt(int i, char *optarg) {
switch(i) {
case LONG_ARGS_JVM_CLASS:
ujvm.class = optarg;
return 1;
case LONG_ARGS_JVM_CLASSPATH:
if (ujvm.classpath_cnt < MAX_CLASSPATH) {
ujvm.classpath[ujvm.classpath_cnt] = optarg;
ujvm.classpath_cnt++;
}
else {
uwsgi_log( "you can specify at most %d --jvm-classpath options\n", MAX_CLASSPATH);
}
return 1;
}
return 0;
}
struct uwsgi_plugin jvm_plugin = {
.name = "jvm",
.init = jvm_init,
.options = uwsgi_jvm_options,
.manage_opt = uwsgi_jvm_manage_opt,
};
+37
View File
@@ -0,0 +1,37 @@
import os,sys
NAME='jvm'
# Snow Leopard
#JVM_INCPATH = "/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Headers/"
#JVM_LIBPATH = "/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Libraries/ -framework JavaVM"
# FreeBSD openjdk7 example
# env UWSGICONFIG_JVM_INCPATH="/usr/local/openjdk7/include -I/usr/local/openjdk7/include/freebsd/" UWSGICONFIG_JVM_LIBPATH="/usr/local/openjdk7/jre/lib/amd64/server" python uwsgiconfig.py --plugin plugins/jvm
# NexentaOS example
# UWSGICONFIG_JVM_INCPATH="/usr/java/include -I /usr/java/include/solaris" UWSGICONFIG_JVM_LIBPATH="/usr/java/jre/lib/i386/" python uwsgiconfig.py --plugin plugins/jvm
# Ubuntu
JVM_INCPATH = "/usr/lib/jvm/java-6-sun-1.6.0.15/include/ -I/usr/lib/jvm/java-6-sun-1.6.0.15/include/linux"
JVM_LIBPATH = "/usr/lib/jvm/java-6-sun-1.6.0.15/jre/lib/i386/server/"
try:
JVM_INCPATH = os.environ['UWSGICONFIG_JVM_INCPATH']
except:
pass
try:
JVM_LIBPATH = os.environ['UWSGICONFIG_JVM_LIBPATH']
except:
pass
CFLAGS = ['-I' + JVM_INCPATH]
LDFLAGS = ['-L' + JVM_LIBPATH]
LIBS = ['-ljvm']
GCC_LIST = ['jvm_plugin']
if os.environ.has_key('LD_RUN_PATH'):
os.environ['LD_RUN_PATH'] += ':' + JVM_LIBPATH
else:
os.environ['LD_RUN_PATH'] = JVM_LIBPATH
+117
View File
@@ -0,0 +1,117 @@
#include "../jvm/jvm.h"
extern struct uwsgi_server uwsgi;
extern struct uwsgi_jvm ujvm;
void uwsgi_jwsgi_init(void) {
}
int uwsgi_jwsgi_request(struct wsgi_request *wsgi_req) {
jmethodID jmid;
int i;
jobject env;
jobject hkey, hval;
jobject response;
jobject status;
jobject headers, header;
jobject body;
jclass hc;
jmethodID hh_size, hh_get;
int hlen;
if (!wsgi_req->uh.pktsize) {
uwsgi_log("Invalid JWSGI request. skip.\n");
return -1;
}
if (uwsgi_parse_vars(wsgi_req)) {
uwsgi_log("Invalid JWSGI request. skip.\n");
return -1;
}
jmid = uwsgi_jvm_get_static_method_id(ujvm.main_class, "jwsgi", "(Ljava/util/Hashtable;)[Ljava/lang/Object;");
uwsgi_log("jwsgi method id = %d\n", jmid);
env = uwsgi_jvm_ht_new();
uwsgi_jvm_exception();
for(i=0;i<wsgi_req->var_cnt;i++) {
uwsgi_jvm_ht_put(env,
uwsgi_jvm_str_new(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len),
uwsgi_jvm_str_new(wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len)
);
// check if something is going wrong during hashtable fill
uwsgi_jvm_exception();
i++;
}
uwsgi_log("env created\n");
uwsgi_jvm_ht_put(env, uwsgi_jvm_str("jwsgi.input"), uwsgi_jvm_fd(wsgi_req->poll.fd));
uwsgi_log("jwsgi.input created\n");
response = (*ujvm.env)->CallObjectMethod(ujvm.env, ujvm.main_class, jmid, env);
uwsgi_jvm_exception();
uwsgi_log("RESPONSE SIZE %d\n", (*ujvm.env)->GetArrayLength(ujvm.env, response));
status = uwsgi_jvm_array_get(response, 0);
uwsgi_jvm_exception();
wsgi_req->headers_size += write(wsgi_req->poll.fd, wsgi_req->protocol, wsgi_req->protocol_len);
wsgi_req->headers_size += write(wsgi_req->poll.fd, " ", 1);
wsgi_req->headers_size += write(wsgi_req->poll.fd, uwsgi_jvm_str2c(status), uwsgi_jvm_strlen2c(status));
wsgi_req->headers_size += write(wsgi_req->poll.fd, "\r\n", 2);
headers = uwsgi_jvm_array_get(response, 1);
hc = uwsgi_jvm_get_object_class(headers);
hh_size = uwsgi_jvm_get_method_id(hc, "size","()I");
hh_get = uwsgi_jvm_get_method_id(hc, "get","(I)Ljava/lang/Object;");
hlen = (*ujvm.env)->CallIntMethod(ujvm.env, headers, hh_size);
for(i=0;i<hlen;i++) {
header = (*ujvm.env)->CallObjectMethod(ujvm.env, headers, hh_get, i);
hkey = uwsgi_jvm_array_get(header, 0);
hval = uwsgi_jvm_array_get(header, 1);
wsgi_req->headers_size += write(wsgi_req->poll.fd, uwsgi_jvm_str2c(hkey), uwsgi_jvm_strlen2c(hkey));
wsgi_req->headers_size += write(wsgi_req->poll.fd, ": ", 2);
wsgi_req->headers_size += write(wsgi_req->poll.fd, uwsgi_jvm_str2c(hval), uwsgi_jvm_strlen2c(hval));
wsgi_req->headers_size += write(wsgi_req->poll.fd, "\r\n", 2);
}
wsgi_req->headers_size += write(wsgi_req->poll.fd, "\r\n", 2);
body = uwsgi_jvm_array_get(response, 2);
wsgi_req->response_size = write(wsgi_req->poll.fd, (*ujvm.env)->GetStringUTFChars(ujvm.env, body, NULL), (*ujvm.env)->GetStringUTFLength(ujvm.env, body));
return 1;
}
void uwsgi_jwsgi_after_request(struct wsgi_request *wsgi_req) {
log_request(wsgi_req);
}
struct uwsgi_plugin jwsgi_plugin = {
.name = "jwsgi",
.modifier1 = 8,
.request = uwsgi_jwsgi_request,
.after_request = uwsgi_jwsgi_after_request,
};
+22
View File
@@ -0,0 +1,22 @@
import os,sys
NAME='jwsgi'
# Snow Leopard
#JVM_INCPATH = "/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Headers/"
#JVM_LIBPATH = "/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Libraries/ -framework JavaVM"
# Ubuntu
JVM_INCPATH = "/usr/lib/jvm/java-6-sun-1.6.0.15/include/ -I/usr/lib/jvm/java-6-sun-1.6.0.15/include/linux"
JVM_LIBPATH = "/usr/lib/jvm/java-6-sun-1.6.0.15/jre/lib/i386/server/"
CFLAGS = ['-I' + JVM_INCPATH]
LDFLAGS = ['-L' + JVM_LIBPATH]
LIBS = ['-ljvm']
GCC_LIST = ['jwsgi_plugin']
if os.environ.has_key('LD_RUN_PATH'):
os.environ['LD_RUN_PATH'] += ':' + JVM_LIBPATH
else:
os.environ['LD_RUN_PATH'] = JVM_LIBPATH
+574 -118
View File
@@ -1,214 +1,670 @@
#include <uwsgi.h>
/* gcc -fPIC -shared -o lua_plugin.so `python2.5-config --cflags` -I /usr/include/lua5.1 -llua5.1 lua_plugin.c */
#include "../../uwsgi.h"
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
extern struct uwsgi_server uwsgi;
static struct uwsgi_lua {
struct lua_State *L ;
struct uwsgi_server *uwsgi;
struct uwsgi_lua {
struct lua_State **L;
char *filename;
} ulua;
static void *uwsgi_lua_alloc(void *ud, void *ptr, size_t osize, size_t nsize) {
if(nsize == 0) {
free(ptr);
return NULL;
}
#define LONG_ARGS_LUA_BASE 17000 + (6 * 100)
#define LONG_ARGS_LUA LONG_ARGS_LUA_BASE + 1
return realloc(ptr, nsize);
#define lca(L, n) ulua_check_args(L, __FUNCTION__, n)
struct option uwsgi_lua_options[] = {
{"lua", required_argument, 0, LONG_ARGS_LUA},
{0, 0, 0, 0},
};
static void ulua_check_args(lua_State *L, const char *func, int n) {
int args = lua_gettop(L);
char error[4096];
if (args != n) {
if (n == 1) {
snprintf(error, 4096, "uwsgi.%s takes 1 parameter", func+10);
}
else {
snprintf(error, 4096, "uwsgi.%s takes %d parameters", func+10, n);
}
lua_pushstring(L, error);
lua_error(L);
}
}
static const char *uwsgi_read_lua(lua_State *L, void *data, size_t *size) {
int fd = *(int *)data;
static char buf[4096];
*size = read(fd, buf, 4096);
static int uwsgi_api_log(lua_State *L) {
if (size == 0) {
return NULL;
const char *logline ;
lca(L, 1);
if (lua_isstring(L, 1)) {
logline = lua_tolstring(L, 1, NULL);
uwsgi_log( "%s\n", logline);
}
return 0;
}
static int uwsgi_api_register_rpc(lua_State *L) {
uint8_t argc = lua_gettop(L);
const char *name;
// a hack for 64bit;
int func;
long lfunc;
if (argc < 2) {
lua_pushnil(L);
return 1;
}
name = lua_tolstring(L, 1, NULL);
lua_pushvalue(L, 2);
func = luaL_ref(L, LUA_REGISTRYINDEX);
uwsgi_log("registered function %d in global table\n", func);
lfunc = func;
if (uwsgi_register_rpc((char *)name, 6, 0, (void *) lfunc)) {
lua_pushnil(L);
}
else {
lua_pushboolean(L, 1);
}
return 1;
}
static char *encode_lua_table(lua_State *L, int index, uint16_t *size) {
char *buf, *ptrbuf;
char *key;
char *value;
size_t keylen;
size_t vallen;
*size = 0;
lua_pushnil(L);
while (lua_next(L, index) != 0) {
if (lua_isstring(L, -2) && lua_isstring(L, -1)) {
key = (char *) lua_tolstring(L, -2, &keylen);
value = (char *) lua_tolstring(L, -1, &vallen);
if (keylen > 0xffff || vallen > 0xffff) continue;
*size += (2+keylen+2+vallen);
}
lua_pop(L, 1);
}
buf = malloc(*size);
if (!buf) {
uwsgi_error("malloc()");
exit(1);
}
ptrbuf = buf;
lua_pushnil(L);
while (lua_next(L, index) != 0) {
if (lua_isstring(L, -2) && lua_isstring(L, -1)) {
key = (char *) lua_tolstring(L, -2, &keylen);
value = (char *) lua_tolstring(L, -1, &vallen);
if (keylen > 0xffff || vallen > 0xffff) continue;
*ptrbuf++ = (uint8_t) (keylen & 0xff);
*ptrbuf++ = (uint8_t) ((keylen >>8) & 0xff);
memcpy(ptrbuf, key, keylen); ptrbuf += keylen;
*ptrbuf++ = (uint8_t) (vallen & 0xff);
*ptrbuf++ = (uint8_t) ((vallen >>8) & 0xff);
memcpy(ptrbuf, value, vallen); ptrbuf += vallen;
}
lua_pop(L, 1);
}
return buf;
}
static int uwsgi_lua_input(lua_State *L) {
static int uwsgi_api_cache_set(lua_State *L) {
int n = lua_gettop(L);
int args = lua_gettop(L);
const char *key ;
const char *value ;
uint64_t expires = 0;
size_t vallen;
static char *buf = "" ;
fprintf(stderr,"richiesti %d bytes\n", n);
if (args > 1) {
//sum = read(ulua.uwsgi->poll.fd,);
key = lua_tolstring(L, 1, NULL);
value = lua_tolstring(L, 2, &vallen);
if (args > 2) {
expires = lua_tonumber(L, 3);
}
lua_pushlstring(L, buf, 0);
uwsgi_cache_set((char *)key, strlen(key), (char *)value, (uint16_t) vallen, expires, 0);
}
lua_pushnil(L);
return 1;
}
static int uwsgi_api_register_signal(lua_State *L) {
int args = lua_gettop(L);
uint8_t sig;
long lhandler;
const char *who;
if (args >= 3) {
sig = lua_tonumber(L, 1);
who = lua_tostring(L, 2);
lua_pushvalue(L, 3);
lhandler = luaL_ref(L, LUA_REGISTRYINDEX);
uwsgi_register_signal(sig, (char *)who, (void *) lhandler, 6);
}
lua_pushnil(L);
return 1;
}
int uwsgi_init(struct uwsgi_server *uwsgi, char *args){
int fd, i;
static int uwsgi_api_cache_get(lua_State *L) {
fprintf(stderr,"Initializing Lua environment...\n");
char *value ;
uint64_t valsize;
const char *key ;
lca(L, 1);
ulua.L = lua_newstate(uwsgi_lua_alloc, NULL);
if (lua_isstring(L, 1)) {
luaL_openlibs(ulua.L);
key = lua_tolstring(L, 1, NULL);
value = uwsgi_cache_get((char *)key, strlen(key), &valsize);
if (value) {
lua_pushlstring(L, value, valsize);
return 1;
}
fd = open(args, O_RDONLY) ;
if (fd < 0) {
perror("open()");
return -1 ;
}
i = lua_load(ulua.L, uwsgi_read_lua, &fd, "uwsgi");
fprintf(stderr,"lua_load: %d\n" ,i);
lua_pushnil(L);
// use a pcall
lua_call(ulua.L, 0, 1);
return 1;
fprintf(stderr,"%s\n", lua_typename(ulua.L, lua_type(ulua.L, -1)));
// ok the lua engine is ready
return 0 ;
}
int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
static int uwsgi_api_send_message(lua_State *L) {
int args = lua_gettop(L);
const char *host;
int uwsgi_fd;
uint8_t modifier1, modifier2;
char *pkt = NULL;
uint16_t pktsize = 0 ;
char buf[4096];
int rlen;
int items = 0;
int input_fd = -1, timeout = -1, input_size = 0;
// is this an fd ?
if (lua_isnumber(L, 1)) {
args = 1;
}
else if (lua_isstring(L, 1)) {
host = lua_tolstring(L, 1, NULL);
uwsgi_fd = uwsgi_connect((char *)host, timeout, 0);
modifier1 = lua_tonumber(L, 2);
modifier2 = lua_tonumber(L, 3);
if (args > 4) {
timeout = lua_tonumber(L, 5);
if (args == 7) {
input_fd = lua_tonumber(L, 6);
input_size = lua_tonumber(L, 7);
}
}
if (lua_istable(L,4)) {
// passed a table
pkt = encode_lua_table(L, 4, &pktsize);
}
if (uwsgi_send_message(uwsgi_fd, modifier1, modifier2, pkt, pktsize, input_fd, input_size, timeout) == -1) {
free(pkt);
lua_pushnil(L);
return 1;
}
free(pkt);
for(;;) {
rlen = uwsgi_waitfd(uwsgi_fd, timeout);
if (rlen > 0) {
rlen = read(uwsgi_fd, buf, 4096);
if (rlen < 0) {
uwsgi_error("read()");
break;
}
else if (rlen > 0) {
lua_pushlstring(L, buf, rlen);
items++;
}
else {
break;
}
}
else if (rlen == 0) {
uwsgi_log("uwsgi request timed out waiting for response\n");
break;
}
}
close(uwsgi_fd);
}
return items;
}
static int uwsgi_api_cl(lua_State *L) {
struct wsgi_request *wsgi_req = current_wsgi_req();
lua_pushnumber(L, wsgi_req->post_cl);
return 1;
}
static int uwsgi_api_req_fd(lua_State *L) {
struct wsgi_request *wsgi_req = current_wsgi_req();
lua_pushnumber(L, wsgi_req->poll.fd);
return 1;
}
static const luaL_reg uwsgi_api[] = {
{"log", uwsgi_api_log},
{"cl", uwsgi_api_cl},
{"req_fd", uwsgi_api_req_fd},
{"send_message", uwsgi_api_send_message},
{"cache_get", uwsgi_api_cache_get},
{"cache_set", uwsgi_api_cache_set},
{"register_signal", uwsgi_api_register_signal},
{"register_rpc", uwsgi_api_register_rpc},
{NULL, NULL}
};
static int uwsgi_lua_input(lua_State *L) {
struct wsgi_request *wsgi_req = current_wsgi_req();
ssize_t sum, len, total;
char *buf, *ptr;
int n = lua_gettop(L);
if (!wsgi_req->post_cl) {
lua_pushlstring(L, "", 0);
return 1;
}
sum = lua_tonumber(L, 2);
if (n > 1) {
uwsgi_log("requested %d bytes\n", sum);
}
buf = malloc(sum);
if (!buf) {
uwsgi_error("malloc()");
}
total = sum;
ptr = buf;
while(total) {
len = read(wsgi_req->poll.fd, ptr, total);
ptr += len;
total -= len;
}
lua_pushlstring(L, buf, sum);
free(buf);
return 1;
}
int uwsgi_lua_init(){
uwsgi_log("Initializing Lua environment... (%d cores)\n", uwsgi.cores);
ulua.L = malloc( sizeof(lua_State*) * uwsgi.cores );
if (!ulua.L) {
uwsgi_error("malloc()");
exit(1);
}
// ok the lua engine is ready
return 0;
}
void uwsgi_lua_app() {
int i;
if (ulua.filename) {
for(i=0;i<uwsgi.cores;i++) {
ulua.L[i] = luaL_newstate();
luaL_openlibs(ulua.L[i]);
luaL_register(ulua.L[i], "uwsgi", uwsgi_api);
if (luaL_loadfile(ulua.L[i], ulua.filename)) {
uwsgi_log("unable to load file %s\n", ulua.filename);
exit(1);
}
// use a pcall
//lua_call(ulua.L[i], 0, 1);
if (lua_pcall(ulua.L[i], 0, 1, 0) != 0) {
uwsgi_log("%s\n", lua_tostring(ulua.L[i], -1));
exit(1);
}
}
}
}
int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
int i;
const char *http ;
size_t slen ;
int raw;
const char *http;
size_t slen;
ssize_t rlen;
char *ptrbuf;
lua_State *L = ulua.L[wsgi_req->async_id];
#ifdef UWSGI_ASYNC
if (wsgi_req->async_status == UWSGI_AGAIN) {
if ((i = lua_pcall(L, 0, 1, 0)) == 0) {
if (lua_type(L, -1) == LUA_TSTRING) {
http = lua_tolstring(L, -1, &slen);
if ( (rlen = write(wsgi_req->poll.fd, http, slen)) != (ssize_t) slen) {
perror("write()");
return UWSGI_OK;
}
wsgi_req->response_size += rlen;
}
lua_pop(L, 1);
lua_pushvalue(L, -1);
return UWSGI_AGAIN;
}
goto clear;
}
#endif
/* Standard WSAPI request */
if (!wsgi_req->uh.pktsize) {
fprintf (stderr, "Invalid WSAPI request. skip.\n");
return -1;
uwsgi_log( "Invalid WSAPI request. skip.\n");
goto clear;
}
if (uwsgi_parse_vars(uwsgi, wsgi_req)) {
fprintf(stderr,"Invalid WSAPI request. skip.\n");
return -1;
}
if (uwsgi_parse_vars(wsgi_req)) {
uwsgi_log("Invalid WSAPI request. skip.\n");
goto clear;
}
// put function in the stack
lua_pushvalue(ulua.L, -1);
lua_getfield(ulua.L, -1, "run");
//lua_getfield(L, LUA_GLOBALSINDEX, "run");
lua_pushvalue(L, -1);
// put cgi vars in the stack
lua_newtable(ulua.L);
lua_pushstring(ulua.L, "");
lua_setfield(ulua.L, -2, "CONTENT_TYPE");
lua_newtable(L);
lua_pushstring(L, "");
lua_setfield(L, -2, "CONTENT_TYPE");
for(i=0;i<wsgi_req->var_cnt;i++) {
lua_pushlstring(ulua.L, (char *)wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len);
lua_pushlstring(L, (char *)wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len);
// transform it in a valid c string TODO this is ugly
ptrbuf = wsgi_req->hvec[i].iov_base+wsgi_req->hvec[i].iov_len ;
*ptrbuf = 0 ;
lua_setfield(ulua.L, -2, (char *)wsgi_req->hvec[i].iov_base);
ptrbuf = wsgi_req->hvec[i].iov_base+wsgi_req->hvec[i].iov_len;
*ptrbuf = 0;
lua_setfield(L, -2, (char *)wsgi_req->hvec[i].iov_base);
i++;
}
// put "input" table
lua_newtable(ulua.L);
lua_pushcfunction(ulua.L, uwsgi_lua_input);
lua_setfield(ulua.L, -2, "read");
lua_setfield(ulua.L, -2, "input");
lua_newtable(L);
lua_pushcfunction(L, uwsgi_lua_input);
lua_setfield(L, -2, "read");
lua_setfield(L, -2, "input");
// call function
i = lua_pcall(ulua.L, 1, 3, 0);
i = lua_pcall(L, 1, 3, 0);
if (i != 0) {
fprintf(stderr,"%s\n", lua_tostring(ulua.L, -1));
lua_pop(ulua.L, 1);
return -1 ;
uwsgi_log("%s\n", lua_tostring(L, -1));
lua_pop(L, 1);
goto clear;
}
fprintf(stderr,"%d %s %s %s\n",i,lua_typename(ulua.L, lua_type(ulua.L, -3)), lua_typename(ulua.L, lua_type(ulua.L, -2)) , lua_typename(ulua.L, lua_type(ulua.L, -1)));
//uwsgi_log("%d %s %s %s\n",i,lua_typename(L, lua_type(L, -3)), lua_typename(L, lua_type(L, -2)) , lua_typename(L, lua_type(L, -1)));
raw = 0;
// send status
if (lua_type(ulua.L, -3) == LUA_TSTRING || lua_type(ulua.L, -3) == LUA_TNUMBER) {
http = lua_tolstring(ulua.L, -3, &slen);
if (write(wsgi_req->poll.fd, "HTTP/1.1 ", 9) != 9) {
if (lua_type(L, -3) == LUA_TSTRING || lua_type(L, -3) == LUA_TNUMBER) {
http = lua_tolstring(L, -3, &slen);
if (write(wsgi_req->poll.fd, wsgi_req->protocol, wsgi_req->protocol_len) != wsgi_req->protocol_len) {
perror("write()");
return -1 ;
goto clear;
}
if (write(wsgi_req->poll.fd, http, slen) != slen) {
if (write(wsgi_req->poll.fd, " ", 1) != 1) {
perror("write()");
return -1 ;
goto clear;
}
if (write(wsgi_req->poll.fd, http, slen) != (ssize_t) slen) {
perror("write()");
goto clear;
}
// a performance hack
ptrbuf = (char *) http;
ptrbuf[3] = 0;
wsgi_req->status = atoi(ptrbuf);
if (write(wsgi_req->poll.fd, "\r\n", 2) != 2) {
perror("write()");
return -1 ;
goto clear;
}
}
else {
raw = 1;
wsgi_req->status = -1;
}
// send headers
lua_pushnil(ulua.L);
while(lua_next(ulua.L, -3) != 0) {
http = lua_tolstring(ulua.L, -2, &slen);
if (write(wsgi_req->poll.fd, http, slen) != slen) {
lua_pushnil(L);
while(lua_next(L, -3) != 0) {
http = lua_tolstring(L, -2, &slen);
if (write(wsgi_req->poll.fd, http, slen) != (ssize_t) slen) {
perror("write()");
return -1 ;
goto clear;
}
if (write(wsgi_req->poll.fd, ": ", 2) != 2) {
perror("write()");
return -1 ;
goto clear;
}
http = lua_tolstring(ulua.L, -1, &slen);
if (write(wsgi_req->poll.fd, http, slen) != slen) {
http = lua_tolstring(L, -1, &slen);
if (write(wsgi_req->poll.fd, http, slen) != (ssize_t) slen) {
perror("write()");
return -1 ;
goto clear;
}
if (write(wsgi_req->poll.fd, "\r\n", 2) != 2) {
perror("write()");
return -1 ;
goto clear;
}
lua_pop(ulua.L, 1);
}
if (write(wsgi_req->poll.fd, "\r\n", 2) != 2) {
perror("write()");
return -1 ;
lua_pop(L, 1);
}
if (!raw) {
if (write(wsgi_req->poll.fd, "\r\n", 2) != 2) {
perror("write()");
goto clear;
}
}
// send body with coroutine
lua_pushvalue(ulua.L, -1);
lua_pushvalue(L, -1);
while ( (i = lua_pcall(ulua.L, 0, 1, 0)) == 0) {
if (lua_type(ulua.L, -1) == LUA_TSTRING) {
http = lua_tolstring(ulua.L, -1, &slen);
if (write(wsgi_req->poll.fd, http, slen) != slen) {
while ( (i = lua_pcall(L, 0, 1, 0)) == 0) {
if (lua_type(L, -1) == LUA_TSTRING) {
http = lua_tolstring(L, -1, &slen);
if ( (rlen = write(wsgi_req->poll.fd, http, slen)) != (ssize_t) slen) {
perror("write()");
return -1 ;
goto clear;
}
//fprintf(stderr,"%.*s\n", slen, http);
}
lua_pop(ulua.L, 1);
lua_pushvalue(ulua.L, -1);
}
wsgi_req->response_size += rlen;
}
lua_pop(L, 1);
lua_pushvalue(L, -1);
#ifdef UWSGI_ASYNC
if (uwsgi.async > 1) {
return UWSGI_AGAIN;
}
#endif
}
lua_pop(ulua.L, 4);
clear:
lua_pop(L, 4);
// set frequency
lua_gc(L, LUA_GCCOLLECT, 0);
return UWSGI_OK;
}
void uwsgi_lua_after_request(struct wsgi_request *wsgi_req) {
if (uwsgi.shared->options[UWSGI_OPTION_LOGGING])
log_request(wsgi_req);
}
int uwsgi_lua_manage_options(int i, char *optarg) {
switch(i) {
case LONG_ARGS_LUA:
ulua.filename = optarg;
return 1;
}
return 0;
}
int uwsgi_lua_magic(char *mountpoint, char *lazy) {
if (!strcmp(lazy+strlen(lazy)-4, ".lua")) {
ulua.filename = lazy;
return 1;
}
else if (!strcmp(lazy+strlen(lazy)-3, ".ws")) {
ulua.filename = lazy;
return 1;
}
return 0;
}
int uwsgi_lua_signal_handler(uint8_t sig, void *handler) {
struct wsgi_request *wsgi_req = current_wsgi_req();
lua_State *L = ulua.L[wsgi_req->async_id];
uwsgi_log("managing signal handler on core %d\n", wsgi_req->async_id);
lua_rawgeti(L, LUA_REGISTRYINDEX, (long) handler);
lua_pushnumber(L, sig);
if (lua_pcall(L, 1, 1, 0) != 0) {
uwsgi_log("error running function `f': %s",
lua_tostring(L, -1));
return -1;
}
return 0;
}
uint16_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, char *buffer) {
uint8_t i;
const char *sv;
size_t sl;
long lfunc = (long) func;
int ifunc = lfunc;
struct wsgi_request *wsgi_req = current_wsgi_req();
lua_State *L = ulua.L[wsgi_req->async_id];
uwsgi_log("get function %d\n", ifunc);
lua_rawgeti(L, LUA_REGISTRYINDEX, ifunc);
for(i=0;i<argc;i++) {
lua_pushstring(L, argv[i]);
}
if (lua_pcall(L, argc, 1, 0) != 0) {
uwsgi_log("error running function `f': %s", lua_tostring(L, -1));
return 0;
}
sv = lua_tolstring(L, -1, &sl);
uwsgi_log("sv = %s sl = %d\n", sv, sl);
if (sl <= 0xffff) {
memcpy(buffer, sv, sl);
return sl;
}
return 0;
}
void uwsgi_after_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
if (uwsgi->shared->options[UWSGI_OPTION_LOGGING])
log_request(wsgi_req);
}
struct uwsgi_plugin lua_plugin = {
.name = "lua",
.modifier1 = 6,
.init = uwsgi_lua_init,
.options = uwsgi_lua_options,
.manage_opt = uwsgi_lua_manage_options,
.request = uwsgi_lua_request,
.after_request = uwsgi_lua_after_request,
.init_apps = uwsgi_lua_app,
.magic = uwsgi_lua_magic,
.signal_handler = uwsgi_lua_signal_handler,
.rpc = uwsgi_lua_rpc,
};
+19 -2
View File
@@ -1,5 +1,22 @@
import os,sys
try:
LUALIB = os.environ['UWSGICONFIG_LUALIB']
except:
LUALIB = 'lua'
try:
LUAINC = os.environ['UWSGICONFIG_LUAINC']
except:
LUAINC = '/usr/include/lua5.1'
try:
LUALIBPATH = os.environ['UWSGICONFIG_LUALIBPATH']
except:
LUALIBPATH = '/usr/lib/lua5.1'
NAME='lua'
CFLAGS = '-I /usr/include/lua5.1'
LDFLAGS = '-llua5.1'
CFLAGS = ['-I%s' % LUAINC]
LDFLAGS = ['-L%s' % LUALIBPATH]
GCC_LIST = ['lua_plugin']
LIBS = ['-l%s' % LUALIB]
+35
View File
@@ -0,0 +1,35 @@
#include "../../uwsgi.h"
struct uwsgi_mono {
char *assembly_name ;
} um;
int uwsgi_mono_init() {
MonoDomain *domain;
MonoAssembly *assembly;
MonoImage *image, *corlib;
domain = mono_jit_init("uwsgi");
corlib = mono_get_corlib();
if (!corlib) {
uwsgi_log("unable to initialize MONO engine\n");
exit(1);
}
image = mono_assembly_get_image(assembly);
}
struct uwsgi_plugin mono_plugin = {
.name = "mono",
.init = uwsgi_mono_init,
};
+88
View File
@@ -0,0 +1,88 @@
#include "../../uwsgi.h"
extern struct uwsgi_server uwsgi;
int use_nagios = 0;
#define LONG_ARGS_NAGIOS 40000
struct option nagios_options[] = {
{"nagios", no_argument, 0, LONG_ARGS_NAGIOS},
{0, 0, 0, 0},
};
int nagios() {
char *tcp_port;
struct pollfd nagios_poll;
// connect and send
if (!use_nagios) {
return 1;
}
if (uwsgi.sockets[0].name == NULL) {
fprintf(stdout, "UWSGI UNKNOWN: you have specified an invalid socket\n");
exit(3);
}
tcp_port = strchr(uwsgi.sockets[0].name, ':');
if (tcp_port == NULL) {
fprintf(stdout, "UWSGI UNKNOWN: you have specified an invalid socket\n");
exit(3);
}
tcp_port[0] = 0;
nagios_poll.fd = connect_to_tcp(uwsgi.sockets[0].name, atoi(tcp_port + 1), uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
if (nagios_poll.fd < 0) {
fprintf(stdout, "UWSGI CRITICAL: could not connect() to workers\n");
exit(2);
}
uwsgi.wsgi_req->uh.modifier1 = UWSGI_MODIFIER_PING;
uwsgi.wsgi_req->uh.pktsize = 0;
uwsgi.wsgi_req->uh.modifier2 = 0;
if (write(nagios_poll.fd, uwsgi.wsgi_req, 4) != 4) {
uwsgi_error("write()");
fprintf(stdout, "UWSGI CRITICAL: could not send ping packet to workers\n");
exit(2);
}
nagios_poll.events = POLLIN;
if (!uwsgi_parse_response(&nagios_poll, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], (struct uwsgi_header *) uwsgi.wsgi_req, uwsgi.wsgi_req->buffer)) {
fprintf(stdout, "UWSGI CRITICAL: timed out waiting for response\n");
exit(2);
}
else {
if (uwsgi.wsgi_req->uh.pktsize > 0) {
fprintf(stdout, "UWSGI WARNING: %.*s\n", uwsgi.wsgi_req->uh.pktsize, uwsgi.wsgi_req->buffer);
exit(1);
}
else {
fprintf(stdout, "UWSGI OK: armed and ready\n");
exit(0);
}
}
// never here
fprintf(stdout, "UWSGI UNKNOWN: probably you hit a bug of uWSGI !!!\n");
exit(3);
}
int nagios_opt(int i, char *optarg) {
switch(i) {
case LONG_ARGS_NAGIOS:
uwsgi.no_initial_output = 1;
use_nagios = 1;
return 1;
}
return 0;
}
struct uwsgi_plugin nagios_plugin = {
.options = nagios_options,
.manage_opt = nagios_opt,
.init = nagios,
};
+7
View File
@@ -0,0 +1,7 @@
NAME='nagios'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['nagios']
+113
View File
@@ -0,0 +1,113 @@
#include "../../uwsgi.h"
extern struct uwsgi_server uwsgi;
struct uwsgi_ping {
char *ping;
int ping_timeout;
} uping;
struct option uwsgi_ping_options[] = {
{"ping", required_argument, 0, LONG_ARGS_PING},
{"ping-timeout", required_argument, 0, LONG_ARGS_PING_TIMEOUT},
{ 0, 0, 0, 0 }
};
static void ping() {
struct uwsgi_header uh;
struct pollfd uwsgi_poll;
// use a 3 secs timeout by default
if (!uping.ping_timeout) uping.ping_timeout = 3;
uwsgi_log("PING uwsgi host %s (timeout: %d)\n", uping.ping, uping.ping_timeout);
uwsgi_poll.fd = uwsgi_connect(uping.ping, uping.ping_timeout, 0);
if (uwsgi_poll.fd < 0) {
exit(1);
}
uh.modifier1 = UWSGI_MODIFIER_PING;
uh.pktsize = 0;
uh.modifier2 = 0;
if (write(uwsgi_poll.fd, &uh, 4) != 4) {
uwsgi_error("write()");
exit(2);
}
uwsgi_poll.events = POLLIN;
if (!uwsgi_parse_response(&uwsgi_poll, uping.ping_timeout, &uh, NULL)) {
exit(1);
}
else {
if (uh.pktsize > 0) {
exit(2);
}
else {
exit(0);
}
}
}
int ping_init() {
if (uping.ping) {
ping();
//never here
}
return 1;
}
/* uwsgi PING|100 */
int uwsgi_request_ping(struct wsgi_request *wsgi_req) {
char len;
uwsgi_log( "PING\n");
wsgi_req->uh.modifier2 = 1;
wsgi_req->uh.pktsize = 0;
len = strlen(uwsgi.shared->warning_message);
if (len > 0) {
// TODO: check endianess ?
wsgi_req->uh.pktsize = len;
}
if (write(wsgi_req->poll.fd, wsgi_req, 4) != 4) {
uwsgi_error("write()");
}
if (len > 0) {
if (write(wsgi_req->poll.fd, uwsgi.shared->warning_message, len)
!= len) {
uwsgi_error("write()");
}
}
return UWSGI_OK;
}
int uwsgi_ping_manage_options(int i, char *optarg) {
switch(i) {
case LONG_ARGS_PING:
uping.ping = optarg;
return 1;
case LONG_ARGS_PING_TIMEOUT:
uping.ping_timeout = atoi(optarg);
return 1;
}
return 0;
}
struct uwsgi_plugin ping_plugin = {
.name = "ping",
.modifier1 = 100,
.options = uwsgi_ping_options,
.manage_opt = uwsgi_ping_manage_options,
.request = uwsgi_request_ping,
.init = ping_init,
};
+5
View File
@@ -0,0 +1,5 @@
NAME='ping'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['ping_plugin']

Some files were not shown because too many files have changed in this diff Show More