Compare commits

...
778 Commits
Author SHA1 Message Date
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
roberto@sirius 3930960159 psycogreen example 2010-04-20 10:30:57 +02:00
roberto@sirius be12175c8a psycopg2 async example 2010-04-20 10:19:00 +02:00
roberto@sirius 02a1847539 async memory fixes 2010-04-19 16:01:13 +02:00
roberto@solaris 0235535658 /dev/poll complete support 2010-04-19 13:43:36 +02:00
roberto@sirius 3af75ca64c default uwsgiconfig.py 2010-04-19 10:14:21 +02:00
roberto@sirius efbe28502d new wsgi_request struct fixes 2010-04-19 10:13:38 +02:00
roberto@solaris 47847ee471 Solaris/Sparc fixes 2010-04-19 08:34:46 +02:00
roberto@sirius 688ffe32a9 urack refactoring 2010-04-15 17:02:29 +02:00
roberto@sirius c6bbe01f3e fix for Plack handler 2010-04-15 12:59:24 +02:00
roberto@sirius 002af6128c UWSGI_FD for plack handler 2010-04-15 11:47:39 +02:00
roberto@sirius 5b5c92a9d7 fix for ruby 1.8.6 2010-04-15 11:01:18 +02:00
roberto@sirius 7d31d73fc5 UWSGI_FD for rack handler 2010-04-15 10:56:25 +02:00
roberto@sirius c5c2c83c65 uWSGI 0.9.5-rc1 2010-04-14 07:26:32 +02:00
roberto@sirius 174116c48b a bunch of fixes for release candidate 2010-04-14 07:25:58 +02:00
roberto@sirius 4be5830fc3 removed base.mk 2010-04-14 07:07:47 +02:00
roberto@sirius 5f55357e17 remove UNBIT makefiles 2010-04-14 07:06:12 +02:00
roberto@sirius 8d033159b8 uwsgiplugin.py for Lua and example 2010-04-13 08:47:33 +02:00
roberto@sirius 299fd9cf8a introduced open PSGI plugin for uWSGI 2010-04-13 08:39:49 +02:00
roberto@sirius 8caee1b15b remove packed attribute from wsgi_request 2010-04-12 13:58:35 +02:00
roberto@sirius c2d963aa0d Plack::Handler:Uwsgi fixes 2010-04-12 13:11:08 +02:00
roberto@sirius 94691b3cc3 Plack::Handler:Uwsgi 2010-04-12 13:07:25 +02:00
roberto@sirius 9073a2856b added uwsgi Rack handler 2010-04-11 20:41:23 +02:00
roberto@sirius 4c26f34239 spooler fixes, and a new example (rrdtool and cron-like spooling) 2010-04-10 09:07:53 +02:00
roberto@sirius ad0cc774e1 shebang on ugreenchat 2010-04-09 11:56:55 +02:00
roberto@sirius d238fc50d0 new uGreen functions, sample comet chat included 2010-04-09 11:13:01 +02:00
roberto@fedora-arm dcf16c994e python headers check 2010-04-08 06:06:54 -04:00
roberto@sirius 65cc44e611 multicast fixes 2010-04-06 14:21:36 +02:00
roberto@sirius 9887177d9a startup logic fixes 2010-04-06 13:58:28 +02:00
roberto@voldemort 6b11777bb3 udp logging fixes 2010-04-06 13:02:04 +02:00
roberto@sirius 604b412f4a remove junk from udp logging 2010-04-06 12:57:17 +02:00
roberto@sirius 1d9da31f18 udp logging support 2010-04-06 12:38:04 +02:00
roberto@sirius fadf640f41 shebang friendly getopt_long() 2010-04-06 10:37:56 +02:00
roberto@sirius 743432a53d Sun fixes 2010-04-02 08:56:02 +02:00
roberto@sirius c1956fc371 /dev/poll support 2010-04-01 10:31:04 +02:00
roberto@sirius 3d098358da SO_ACCEPTFILTER 2010-04-01 09:25:15 +02:00
roberto@sirius 757e908372 uGreen timeout implementation 2010-03-31 15:17:04 +02:00
roberto@sirius dd12caa6f3 interrupt compilation if XML+libxml2 is requested but libxml2 headers are unavailable 2010-03-31 11:34:10 +02:00
roberto@sirius 0bfa5c4f46 Wally's patch for not compiled-in options 2010-03-31 11:15:24 +02:00
roberto@sirius cb252e4f0a OSX re-fix 2010-03-31 10:01:07 +02:00
roberto@sirius bdab4dcf84 uGreen fd async waiting support 2010-03-31 09:57:16 +02:00
roberto@sirius 474860cd39 uGreen configurable stack size 2010-03-30 20:07:50 +02:00
roberto@fierobecco 82f722b1f9 OSX fixes for uGreen 2010-03-29 13:05:36 +02:00
roberto@sirius 919501e92c uGreen little refactoring and fixes 2010-03-29 10:30:03 +02:00
roberto@sirius b1f3e48b2b uGreen fix 2010-03-28 18:21:23 +02:00
roberto@sirius 314df1d809 ugreen support 2010-03-28 18:18:23 +02:00
roberto@sirius 0416914951 fixed async wsgi mode 2010-03-26 17:01:13 +01:00
roberto@sirius 159a5660b2 Added tag 0.9.5beta2 for changeset 63560de14789 2010-03-26 09:24:55 +01:00
roberto@sirius 6ea9ee4ee9 re-enabled environment 2010-03-26 09:24:46 +01:00
roberto@sirius c60a81db47 uWSGI 0.9.5beta2 2010-03-26 09:19:03 +01:00
roberto@sirius b71634c76b erlang support is dependent on python embedded module 2010-03-26 09:17:53 +01:00
roberto@sirius 9a23c42262 another setrlimit() fix 2010-03-26 09:01:37 +01:00
roberto@sirius 680df4cff6 setrlimit() fixes 2010-03-26 08:59:33 +01:00
roberto@sirius 27fa8df9e6 automatically rise RLIMIT_NOFILE if possibile 2010-03-26 08:45:40 +01:00
roberto@sirius 2151b17aa3 check on RLIMIT_NOFILE beforse allocating async cores 2010-03-26 08:34:37 +01:00
roberto@sirius b93d0cc2b0 kevent() on pre-forking fix 2010-03-25 17:55:08 +01:00
roberto@sirius 1729275f8c async fix for fd waiting on kevent() 2010-03-25 17:35:58 +01:00
roberto@sirius 9b2460f8df another fix errno in tests.iobound_async 2010-03-25 17:21:05 +01:00
roberto@sirius 5451ff490c fix errno in tests.iobound_async 2010-03-25 17:17:33 +01:00
roberto@sirius 5a828aefdc python 3k full support 2010-03-25 16:04:40 +01:00
roberto@unbit 6a4332ca4d use distutils.sysconfig instead of python-config 2010-03-25 11:07:12 +01:00
roberto@sirius 7f3750b174 no fd-leak in stackless and async mode 2010-03-25 08:05:17 +01:00
roberto@sirius 7b1672497e stackless python support 2010-03-24 15:32:36 +01:00
roberto@sirius 113223567a typo fixes 2010-03-23 10:47:48 +01:00
roberto@fierobecco ecf23f93d1 osx erlang help 2010-03-22 15:32:01 +01:00
roberto@freebsd 2504af4dd1 FreeBSD sendfile fixes 2010-03-22 15:12:17 +01:00
roberto@netbsd c340e972ad NetBSD sendfile fixes, memory report and typecasting 2010-03-22 15:45:03 +01:00
roberto@sirius e382de291f expat implementation 2010-03-22 11:14:58 +01:00
roberto@sirius 51d97fadd9 nagios refactoring 2010-03-22 09:06:32 +01:00
roberto@sirium 878b515e23 code refactoring 2010-03-22 08:22:21 +01:00
roberto@sirius 03bdaa50b6 linux sendfile fix 2010-03-21 21:05:33 +01:00
roberto@sirius 34dbfc597e proxy refactoring 2010-03-21 21:01:27 +01:00
roberto@fierobecco 05efe4b7b3 kqueue fixes, sendfile osx, fix on apache2 module 2010-03-21 19:50:20 +01:00
roberto@sirius a18bc5f148 sendfile async implementation, still broken on BSD 2010-03-21 14:38:26 +01:00
roberto@sirius 9852b2fa62 async sleep implementation, kqueue re-broken, profiler leaks memory 2010-03-21 08:53:36 +01:00
roberto@sirius 9cedbb6716 WSGI handler refactoring 2010-03-18 18:14:06 +01:00
roberto@sirius 96a6c5eff4 report async switches 2010-03-18 17:42:22 +01:00
roberto@sirius e5233f09cc fix for a stupid typo 2010-03-18 13:53:53 +01:00
roberto@sirius 2f7bf001e8 new async test for I/O 2010-03-18 13:39:41 +01:00
roberto@fierobecco 1caea3dbeb async support for BSD systems (kqueue based) 2010-03-18 13:35:11 +01:00
roberto@sirius 6805e5ee9f merge 2010-03-18 12:38:21 +01:00
roberto@sirius 82f33591ae revert snmp fix 2010-03-18 12:37:37 +01:00
roberto@sirius b3e3e2ca1d async.c (only epoll) 2010-03-18 12:34:23 +01:00
roberto@sirius 4ae0361f6d little snmp fix 2010-03-18 12:34:12 +01:00
roberto@sirius.local 5706dd0a31 remove non-included option from getopt 2010-03-18 09:09:28 +01:00
roberto@sirius d8cd5580b7 preliminary async support 2010-03-17 18:08:53 +01:00
roberto@sirius e16c9b46ed little tag fix 2010-03-12 11:23:26 +01:00
roberto@sirius 86d28b2654 uWSGI 0.9.5beta1 2010-03-12 11:22:37 +01:00
roberto@sirius 09bc058e88 goodbye to ROCK_SOLID 2010-03-12 11:01:34 +01:00
roberto@sirius 0bf55fc1f9 Yann is right, remove the interactive setup.py 2010-03-11 18:26:23 +01:00
roberto@sirius e05edd9f82 almost ready SNMP support 2010-03-11 18:24:37 +01:00
roberto@sirius aa9c5331d4 re-indent all the code 2010-03-11 12:39:30 +01:00
roberto@sirius 665511e6fa updated --help 2010-03-11 10:06:06 +01:00
roberto@sirius 41190a5336 UWSGI_VERSION --version 2010-03-11 10:04:21 +01:00
roberto@fierobecco f2b72814a6 kqueue fixes for connect() 2010-03-10 16:11:28 +01:00
roberto@sirius 67d49defb6 remove useless service_unavailable in proxy 2010-03-10 15:51:22 +01:00
roberto@sirius bf1f800cf4 epoll fixes 2010-03-10 15:50:06 +01:00
roberto@fierobecco 55a95ac4b4 kqueue support and apache2 fix 2010-03-10 14:42:14 +01:00
roberto@sirius 820caa5364 python3.x compatible uwsgiconfig.py 2010-03-10 08:14:28 +01:00
roberto@sirius 67ce14dfa8 other 64 bit fixes 2010-03-10 07:09:18 +01:00
roberto@sirius dc16e8eb38 sendfile 64bit fixes 2010-03-09 21:42:37 +01:00
roberto@sirius fc0de78d88 fixed conditional proxy compilatio 2010-03-09 09:12:35 +01:00
roberto@sirius 1ffecc7939 setup.py build_ext interactive 2010-03-09 08:55:30 +01:00
roberto@sirius 2b4759e5e1 setup.py write flush (10) 2010-03-09 08:54:55 +01:00
roberto@sirius 779ab3702a setup.py write flush (9) 2010-03-09 08:54:21 +01:00
roberto@sirius 25fe41dd50 setup.py write flush (8) 2010-03-09 08:53:47 +01:00
roberto@sirius 1c03935b76 setup.py write flush (7) 2010-03-09 08:50:32 +01:00
roberto@sirius 6b10370c0a setup.py write flush (6) 2010-03-09 08:49:20 +01:00
roberto@sirius e84c3808e9 setup.py write flush (5) 2010-03-09 08:48:51 +01:00
roberto@sirius b9ff3f87d0 setup.py write flush (4) 2010-03-09 08:47:28 +01:00
roberto@sirius 7a6d40c258 setup.py write flush (3) 2010-03-09 08:46:03 +01:00
roberto@sirius 5c211817b7 setup.py write flush (2) 2010-03-09 08:33:37 +01:00
roberto@sirius 21b2769edd setup.py write flush 2010-03-09 08:31:33 +01:00
roberto@sirius baff440f18 setup.py update 2010-03-09 08:30:02 +01:00
roberto@sirius 793dcd92d2 setup.py print input to stderr 2010-03-09 08:28:38 +01:00
roberto@sirius 1d203021c7 new setup.py fixes 2010-03-09 08:18:33 +01:00
roberto@sirius.local d38cc66738 better default values for trunk 2010-03-08 15:49:01 +01:00
roberto@sirius 603351c736 interactive setup.py 2010-03-08 15:44:11 +01:00
roberto@sirius ae5b69b19c setup.py new try (3) 2010-03-08 15:24:12 +01:00
roberto@sirius 0229a9727e setup.py new try (2) 2010-03-08 15:18:58 +01:00
roberto@sirius da571c2515 setup.py new try 2010-03-08 15:17:44 +01:00
roberto@sirius d3160c3f60 setup.py fix 2010-03-08 13:37:38 +01:00
roberto@sirius 175ef65d9f new build system 2010-03-08 13:25:02 +01:00
roberto@sirius 8a572a642e a bit of vacuum 2010-03-08 11:05:02 +01:00
roberto@sirius 70a51c2909 erlang fixes and rpc 2010-03-05 15:32:49 +01:00
roberto@sirius 8b32564b05 proxy.c 2010-03-04 17:25:13 +01:00
roberto@sirius c0ada5e52a wsgi file support 2010-03-04 16:54:26 +01:00
roberto@sirius 0ffcb9e05e the uWSGI proxy 2010-03-04 16:48:33 +01:00
roberto@sirius 5a279bb170 new binary-path options, useful for chroot reloads and cherokee wizard 2010-03-03 14:10:51 +01:00
roberto@sirius 757049d9da nagios plugin mode 2010-03-02 17:57:09 +01:00
roberto@sirius.local 8674787692 leak free ( i hope ) erlang node 2010-03-02 11:50:18 +01:00
roberto@sirius 3654016c53 complete erlang integration. Now working on timeout and memory management 2010-03-01 18:51:11 +01:00
roberto@sirius 4dbc15a253 big erlang update, still a lot of memory problems 2010-03-01 18:06:38 +01:00
roberto@sirius 3d55ab8327 contrib reorganization 2010-03-01 14:11:36 +01:00
roberto@sirius f4e336026b Erlang and new XML configuration 2010-03-01 14:06:56 +01:00
roberto@sirius ed90e0cf4b Makefile.Py25 2010-03-01 14:05:04 +01:00
roberto@sirius bed7682a3b useful XML support, first commit of uwsgiconfig.py 2010-03-01 14:02:36 +01:00
roberto@sirius 3874d3e610 stronger reload recognition 2010-02-15 14:55:20 +01:00
roberto@sirius d378d42c4c more getsockopt fixes 2010-02-15 12:09:18 +01:00
roberto@sirius 4faeb852c6 fix socket_type initialization 2010-02-15 11:33:10 +01:00
roberto@sirius 27177a4df9 trying to fix strange darwin behaviour on getsockopt 2010-02-15 10:03:56 +01:00
roberto@sirius 4ee9b36579 lower the scheduler priority of the spooler process 2010-02-14 11:20:13 +01:00
roberto@sirius c06a1626ed print a warning when the spooler dies 2010-02-14 11:03:09 +01:00
roberto@sirius 86787b796a fixed bug signalled by Valery Masiutsin 2010-02-14 10:58:45 +01:00
roberto@sirius 3bae35805b uwsgi.functions refactoring 2010-02-12 15:52:06 +01:00
roberto@sirius f26e79fb09 support for multiple --pythonpath options 2010-02-12 15:18:03 +01:00
roberto@sirius b72fc0a178 UWSGI_SCHEME for apache 2010-02-12 15:11:15 +01:00
roberto@sirius f1853568f9 latest Joerg Sonnenberger patches and some fix to the spooler 2010-02-12 14:57:19 +01:00
roberto@sirius 2785cd3065 remove the automatic locking for sharedarea, and export the uwsgi.lock() and uwsgi.unlock() functions 2010-02-12 10:41:41 +01:00
roberto@sirius a8a497e431 portability fix on spooler code 2010-02-11 10:36:55 +01:00
roberto@sirius 710588fcfd fixed plugin initialization 2010-02-11 09:55:02 +01:00
roberto@sirius a66aad02d8 added Joerg Sonnenberger UWSGI_SCHEME patch 2010-02-10 18:29:17 +01:00
roberto@freebsd 651dacad3a memory report for FreeBSD (finally) 2010-02-10 18:21:52 +01:00
roberto@sirius fdeb2e26cf fixed stupid check 2010-02-10 17:54:25 +01:00
roberto@sirius d5d5b87627 new configuration way 2010-02-10 17:52:13 +01:00
roberto@sirius 67c1a547af SCTP support is disabled and experimental 2010-02-10 17:31:32 +01:00
roberto@sirius ed9c99c417 ucheck.py for automagic makefiles 2010-02-10 17:30:29 +01:00
roberto@sirius 2e29b6b234 first (destructive) public commit for the 0.9.5 branch 2010-02-10 17:28:58 +01:00
roberto@sirius e0882ed8df big update: hooks and plugins 2010-02-07 23:06:24 +01:00
roberto@sirius.local a6b42af85a remove get_free_memory function. Is useless on modern systems 2010-02-04 14:02:30 +01:00
roberto@fierobecco 595e99a0c6 fix for 64 bit systems 2010-02-04 12:21:09 +01:00
roberto@sirius 54f666f214 fix warning 2010-02-04 11:55:35 +01:00
roberto@sirius f1fad65b43 fix warning 2010-02-04 11:54:25 +01:00
roberto@sirius 40fb6ffa91 print arch size 2010-02-04 11:52:24 +01:00
roberto@sirius d83a685d01 print address space limit only if limited 2010-02-04 11:48:09 +01:00
roberto@sirius e7b346d3d9 address space limiting with --limit-as 2010-02-04 11:37:04 +01:00
roberto@fierobecco 25ec7aadc0 OSX free memory monitoring 2010-02-04 10:33:06 +01:00
roberto@sirius f7ef3161e4 huge update, uwsgi.sorry_i_need_block(), uwsgi.log(), uwsgi.worker_id(), uwsgi.request_id(), uwsgi.disconnect() 2010-02-04 09:51:41 +01:00
roberto@sirius 2cd731f36d follow Igor coding style 2010-01-29 08:52:38 +01:00
roberto@sirius 15a0b7fbc9 nginx indentation fixes 2010-01-29 08:29:41 +01:00
roberto@sirius f33d16edb7 base for the uwsgi.sorry_i_have_to_block() hint 2010-01-29 08:16:56 +01:00
roberto@sirius 6fdb5cac37 working setup.py 2010-01-26 17:38:31 +01:00
roberto@sirius 20f7e4f0bc setup.py 2010-01-26 17:37:09 +01:00
roberto@sirius 0c1e9080af setup.py 2010-01-26 17:34:59 +01:00
roberto@sirius 1ceb82af59 setup.py 2010-01-26 17:34:22 +01:00
roberto@sirius ace76d686d setup.py 2010-01-26 17:32:21 +01:00
roberto@sirius a7bb9bd2bb setup.py 2010-01-26 17:27:33 +01:00
roberto@sirius aa39cc0eca better setup.py (third try) 2010-01-26 16:43:14 +01:00
roberto@sirius 74c88f21a9 better setup.py (second try) 2010-01-26 16:40:49 +01:00
roberto@sirius c03e94f97e better setup.py 2010-01-26 16:29:20 +01:00
roberto@sirius be4da2e8d9 third try for pip install 2010-01-26 16:19:39 +01:00
roberto@sirius d781a02eed second try for pip install 2010-01-26 16:15:35 +01:00
roberto@sirius fd42997e8f first try for pip install 2010-01-26 16:14:33 +01:00
roberto@sirius 6be13c2e04 uwsgi.get_option and uwsgi.set_option 2010-01-26 15:17:46 +01:00
roberto@sirius 63f63adda6 TCP_DEFER_ACCEPT optimization, automagic setup.py, dynamic options, python argv customization, refactoring of embedded module 2010-01-26 10:19:51 +01:00
roberto@sirius c0904e42fc setup.py 2010-01-22 16:39:59 +01:00
roberto@sirius 8b8f1d60ed uwsgi.unbit 2010-01-22 13:24:18 +01:00
roberto@sirius 5a6850e64b uWSGI 0.9.4 2010-01-21 15:18:17 +01:00
roberto@sirius cc6e9924b8 endianess fixes for lighttpd module 2010-01-21 14:36:07 +01:00
roberto@sirius 816998155e little bugfix for 64bit apache2 2010-01-21 14:04:56 +01:00
roberto@silente b2ffd406e3 apache2 module for 0.9.4 2010-01-21 13:07:52 +01:00
roberto@sirius 713ffe38b4 apache2 endianess fixes 2010-01-21 12:32:07 +01:00
roberto@sirius 1810af7b2d report load of the uWSGI workers in the django admin app 2010-01-21 09:42:58 +01:00
roberto@sirius d0fb89c783 print the listen backlog, as it is an important value for tuning 2010-01-21 09:06:08 +01:00
roberto@gambit b0c23faeeb unbit makefile for py2.6 2010-01-20 09:52:43 +01:00
roberto@sirius edc4aa42c8 fix warnings 2010-01-20 09:43:12 +01:00
roberto@sirius dda8c2ffaa unbit fixes (2) 2010-01-20 09:41:23 +01:00
roberto@sirius 7059fd8d88 unbit fixes 2010-01-20 09:40:08 +01:00
roberto@sirius dad81ce7bd paste.deploy support 2010-01-19 17:42:52 +01:00
roberto@sirius 277afccf64 new --pythonpath long options and django admin module 2010-01-19 14:27:09 +01:00
roberto@sirius 3854d14867 DragonflyBSD support 2010-01-18 16:26:14 +01:00
roberto@sirius e3a67a9bcd vacuum 2010-01-18 14:55:18 +01:00
roberto@sirius a51b19669c uWSGI 0.9.4-rc1 2010-01-18 14:45:13 +01:00
roberto@sirius 2707860bc5 removed the cherokee handler as it is included in the official cherokee distribution 2010-01-18 14:40:54 +01:00
roberto@sirius 7c69aade57 remove the chroot warning on unbit systems 2010-01-15 09:41:20 +01:00
roberto@sirius 38c5d3d4b5 a little linux warning for chroot environments 2010-01-15 09:40:28 +01:00
roberto@sirius 065b992bf9 fix worker id for single process environment 2010-01-15 09:32:52 +01:00
roberto@sirius 3b93696775 --chroot, --gid, --uid implementation (root only) 2010-01-14 15:33:18 +01:00
roberto@sirius 62534b2490 freebsd fixes 2010-01-14 13:48:24 +01:00
roberto@voldemort 5018c152e9 new UNBIT makefiles 2010-01-14 12:13:59 +01:00
roberto@voldemort 57fc6bcef0 remove python2.6 support for rock_solid 2010-01-14 12:07:08 +01:00
roberto@voldemort 36f26dba85 remove useless LLVM files, they will be in the experimental directory after the 0.9.4 release 2010-01-14 12:06:21 +01:00
roberto@voldemort 6062bf8a72 new makefiles for py2.4, 3.0, 3.1 and ROCK_SOLID mode 2010-01-14 11:54:51 +01:00
roberto@voldemort 0152fb077b fix for process management 2010-01-14 10:29:42 +01:00
roberto@voldemort 440d42303d another typo. damn. 2010-01-13 09:30:36 +01:00
roberto@voldemort 72e28580a6 fix typo 2010-01-13 09:30:01 +01:00
roberto@sirius acf7984eb3 finally a working (and fast) lighttpd module 2010-01-11 18:38:32 +01:00
roberto@sirius bda58ad5cd lighttpd module 2010-01-11 17:33:48 +01:00
roberto@sirius 89258474ad allow single-app definition using 'application' callable 2010-01-11 17:00:43 +01:00
roberto@sirius dc01fc4b42 help/usage for 0.9.4 release 2010-01-11 16:47:14 +01:00
roberto@sirius 0dd5add615 no-server mode (useful for using uwsgi embedded module in standalone apps) 2010-01-11 16:24:36 +01:00
254 changed files with 35381 additions and 7124 deletions
+15
View File
@@ -0,0 +1,15 @@
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
+288
View File
@@ -1,3 +1,291 @@
*** march 2011 ***
* 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] *
- fix sendfile on 64bit
- include setup.py
*** february 2010 ***
* Maintenance release *
- better support for NetBSD
- threading fix for FreeBSD
- sendfile portability fixes
- new makefiles
- example app for testing static file serving
- fixes for ROCK_SOLID mode
*** january 2010 ***
- Integrated Spooler
- better error management
- long options
- clustering functions
- experimental lighttpd module
- official support for OpenBSD and OpenSolaris
- FastFuncs
- new functions for embedded module
- reliable harakiri
- better Makefiles
- python threads support in master process
- proper timeout handling in apache2 module
- endianess fixes all over the place
- paste support
- Django app for managing and monitoring the uWSGI server
- options for changin uid/gid and chrooting when run by root
- lot of bugfixes and optimizations
*** 20091129 Version 0.9.3 ***
- Nginx 0.7.x module
+2 -13
View File
@@ -1,13 +1,2 @@
CC=gcc
PYTHON_CFLAGS=`python2.5-config --cflags`
PYTHON_LIBS=`python2.5-config --libs`
XML_CFLAGS=`xml2-config --cflags`
XML_LIBS=`xml2-config --libs`
CFLAGS=$(PYTHON_CFLAGS) $(XML_CFLAGS)
LD_FLAGS=$(PYTHON_LIBS) $(XML_LIBS)
PROGRAM=uwsgi
include base.mk
all:
python uwsgiconfig.py --build
-31
View File
@@ -1,31 +0,0 @@
CC=/usr/lib/llvm/llvm/gcc-4.2/bin/llvm-gcc
PYTHON_CFLAGS=`python2.5-config --cflags`
PYTHON_LIBS=`python2.5-config --libs`
XML_CFLAGS=`xml2-config --cflags`
XML_LIBS=`xml2-config --libs`
CFLAGS=$(PYTHON_CFLAGS) $(XML_CFLAGS)
LD_FLAGS=$(PYTHON_LIBS) $(XML_LIBS)
PROGRAM=uwsgi
all: uwsgi
uwsgi: utils.o socket.o pymodule.o main.o
$(CC) $(LD_FLAGS) utils.o socket.o pymodule.o main.o -o $(PROGRAM)
utils.o: utils.c
$(CC) -c $(CFLAGS) utils.c
socket.o: socket.c
$(CC) -c $(CFLAGS) socket.c
pymodule.o: uwsgi_pymodule.c
$(CC) -c $(CFLAGS) -o pymodule.o uwsgi_pymodule.c
main.o: uwsgi.c
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
clean:
rm -f utils.o socket.o pymodule.o main.o
-31
View File
@@ -1,31 +0,0 @@
CC=/usr/lib/llvm/llvm/gcc-4.2/bin/llvm-gcc
PYTHON_CFLAGS=`python2.6-config --cflags`
PYTHON_LIBS=`python2.6-config --libs`
XML_CFLAGS=`xml2-config --cflags`
XML_LIBS=`xml2-config --libs`
CFLAGS=$(PYTHON_CFLAGS) $(XML_CFLAGS)
LD_FLAGS=$(PYTHON_LIBS) $(XML_LIBS)
PROGRAM=uwsgi26
all: uwsgi
uwsgi: utils.o socket.o pymodule.o main.o
$(CC) $(LD_FLAGS) utils.o socket.o pymodule.o main.o -o $(PROGRAM)
utils.o: utils.c
$(CC) -c $(CFLAGS) utils.c
socket.o: socket.c
$(CC) -c $(CFLAGS) socket.c
pymodule.o: uwsgi_pymodule.c
$(CC) -c $(CFLAGS) -o pymodule.o uwsgi_pymodule.c
main.o: uwsgi.c
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
clean:
rm -f utils.o socket.o pymodule.o main.o
+2
View File
@@ -0,0 +1,2 @@
all:
python2.4 uwsgiconfig.py --build
+2
View File
@@ -0,0 +1,2 @@
all:
python2.5 uwsgiconfig.py --build
+2 -13
View File
@@ -1,13 +1,2 @@
CC=gcc
PYTHON_CFLAGS=`python2.6-config --cflags`
PYTHON_LIBS=`python2.6-config --libs`
XML_CFLAGS=`xml2-config --cflags`
XML_LIBS=`xml2-config --libs`
CFLAGS=$(PYTHON_CFLAGS) $(XML_CFLAGS)
LD_FLAGS=$(PYTHON_LIBS) $(XML_LIBS)
PROGRAM=uwsgi26
include base.mk
all:
python2.6 uwsgiconfig.py --build
+2
View File
@@ -0,0 +1,2 @@
all:
python2.7 uwsgiconfig.py --build
+2
View File
@@ -0,0 +1,2 @@
all:
python3.0 uwsgiconfig.py --build
+2
View File
@@ -0,0 +1,2 @@
all:
python3.1 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
-29
View File
@@ -1,29 +0,0 @@
CC=gcc
PYTHON_CFLAGS=`python2.6-config --cflags`
PYTHON_LIBS=`python2.6-config --libs`
CFLAGS=$(PYTHON_CFLAGS) -DROCK_SOLID
LD_FLAGS=$(PYTHON_LIBS) -DROCK_SOLID
PROGRAM=uwsgi26_rs
all: uwsgi
uwsgi: utils.o socket.o pymodule.o main.o
$(CC) $(LD_FLAGS) utils.o socket.o pymodule.o main.o -o $(PROGRAM)
utils.o: utils.c
$(CC) -c $(CFLAGS) utils.c
socket.o: socket.c
$(CC) -c $(CFLAGS) socket.c
pymodule.o: uwsgi_pymodule.c
$(CC) -c $(CFLAGS) -o pymodule.o uwsgi_pymodule.c
main.o: uwsgi.c
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
clean:
rm -f utils.o socket.o pymodule.o main.o
-26
View File
@@ -1,26 +0,0 @@
CC=gcc
PYTHON_CFLAGS=`python2.4-config --cflags`
PYTHON_LIBS=`python2.4-config --libs`
CFLAGS=$(PYTHON_CFLAGS) -DUNBIT -D_GNU_SOURCE
LD_FLAGS=$(PYTHON_LIBS) -DUNBIT -D_GNU_SOURCE
PROGRAM=/usr/share/unbit/uwsgi24
all: clean uwsgi
uwsgi: utils.o pymodule.o main.o
$(CC) $(LD_FLAGS) main.o utils.o pymodule.o -o $(PROGRAM)
utils.o: utils.c
$(CC) -c $(CFLAGS) utils.c
pymodule.o: uwsgi_pymodule.c
$(CC) -c $(CFLAGS) -o pymodule.o uwsgi_pymodule.c
main.o: uwsgi.c
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
clean:
rm -f utils.o pymodule.o main.o
-26
View File
@@ -1,26 +0,0 @@
CC=gcc
PYTHON_CFLAGS=`python2.5-config --cflags`
PYTHON_LIBS=`python2.5-config --libs`
CFLAGS=$(PYTHON_CFLAGS) -DUNBIT -D_GNU_SOURCE
LD_FLAGS=$(PYTHON_LIBS) -DUNBIT -D_GNU_SOURCE
PROGRAM=/usr/share/unbit/uwsgi
all: clean uwsgi
uwsgi: utils.o pymodule.o main.o
$(CC) $(LD_FLAGS) main.o utils.o pymodule.o -o $(PROGRAM)
utils.o: utils.c
$(CC) -c $(CFLAGS) utils.c
pymodule.o: uwsgi_pymodule.c
$(CC) -c $(CFLAGS) -o pymodule.o uwsgi_pymodule.c
main.o: uwsgi.c
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
clean:
rm -f utils.o pymodule.o main.o
-33
View File
@@ -1,33 +0,0 @@
CC=gcc
PYBASE=/opt/packages/python/26
PATH := ${PATH}:$(PYBASE)/bin
LD_LIBRARY_PATH= $(PYBASE)/lib
export LD_LIBRARY_PATH
PYTHON_CFLAGS=`python2.6-config --cflags`
PYTHON_LIBS=`python2.6-config --libs`
CFLAGS=$(PYTHON_CFLAGS) -DUNBIT -D_GNU_SOURCE
LD_FLAGS=$(PYTHON_LIBS) -DUNBIT -D_GNU_SOURCE -L $(LD_LIBRARY_PATH)
PROGRAM=/usr/share/unbit/uwsgi26
all: clean uwsgi
uwsgi: utils.o pymodule.o main.o
$(CC) $(LD_FLAGS) main.o utils.o pymodule.o -o $(PROGRAM)
utils.o: utils.c
$(CC) -c $(CFLAGS) utils.c
pymodule.o: uwsgi_pymodule.c
$(CC) -c $(CFLAGS) -o pymodule.o uwsgi_pymodule.c
main.o: uwsgi.c
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
clean:
rm -f utils.o pymodule.o main.o
-30
View File
@@ -1,30 +0,0 @@
CC=gcc
PYBASE=/opt/packages/python/30
PATH := ${PATH}:$(PYBASE)/bin
LD_LIBRARY_PATH= $(PYBASE)/lib
export LD_LIBRARY_PATH
PYTHON_CFLAGS=`python3.0-config --cflags`
PYTHON_LIBS=`python3.0-config --libs`
CFLAGS=$(PYTHON_CFLAGS) -DUNBIT -D_GNU_SOURCE -DPYTHREE
LD_FLAGS=$(PYTHON_LIBS) -DUNBIT -D_GNU_SOURCE -DPYTHREE -L $(LD_LIBRARY_PATH)
PROGRAM=/usr/share/unbit/uwsgi30
all: clean uwsgi
uwsgi: utils.o main.o
$(CC) $(LD_FLAGS) main.o utils.o -o $(PROGRAM)
utils.o: utils.c
$(CC) -c $(CFLAGS) utils.c
main.o: uwsgi.c
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
clean:
rm -f utils.o main.o
-30
View File
@@ -1,30 +0,0 @@
CC=gcc
PYBASE=/opt/packages/python/31
PATH := ${PATH}:$(PYBASE)/bin
LD_LIBRARY_PATH= $(PYBASE)/lib
export LD_LIBRARY_PATH
PYTHON_CFLAGS=`python3.1-config --cflags`
PYTHON_LIBS=`python3.1-config --libs`
CFLAGS=$(PYTHON_CFLAGS) -DUNBIT -D_GNU_SOURCE -DPYTHREE
LD_FLAGS=$(PYTHON_LIBS) -DUNBIT -D_GNU_SOURCE -DPYTHREE -L $(LD_LIBRARY_PATH)
PROGRAM=/usr/share/unbit/uwsgi31
all: clean uwsgi
uwsgi: utils.o main.o
$(CC) $(LD_FLAGS) main.o utils.o -o $(PROGRAM)
utils.o: utils.c
$(CC) -c $(CFLAGS) utils.c
main.o: uwsgi.c
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
clean:
rm -f utils.o main.o
+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 */
};
+169 -50
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
@@ -24,8 +24,8 @@ To compile:
apxs2 -i -c mod_uwsgi.c
(OSX)
sudo apxs -i -a -c mod_uwsgi.c
(OSX 64bit)
sudo apxs -i -a -c -Wc,'-arch x86_64' -Wl,'-arch x86_64' mod_uwsgi.c
(OSX Universal binary)
sudo apxs -i -a -c -Wc,"-arch ppc -arch i386 -arch x86_64" -Wl,"-arch ppc -arch i386 -arch x86_64" mod_uwsgi.c
Configure:
@@ -71,25 +71,73 @@ typedef struct {
uint8_t modifier1;
uint8_t modifier2;
char script_name[256];
char scheme[9];
int cgi_mode ;
} uwsgi_cfg;
module AP_MODULE_DECLARE_DATA uwsgi_module;
#if APR_IS_BIGENDIAN
static uint16_t uwsgi_swap16(uint16_t x) {
return (uint16_t) ((x & 0xff) << 8 | (x & 0xff00) >> 8);
}
#endif
static int uwsgi_add_var(struct iovec *vec, int i, char *key, char *value, uint16_t *pkt_size) {
vec[i].iov_base = &vec[i+1].iov_len ;
vec[i].iov_len = 2 ;
#if APR_IS_BIGENDIAN
char *ptr;
vec[i+2].iov_base = key ;
vec[i+2].iov_len = strlen(key) ;
#else
vec[i+1].iov_base = key ;
vec[i+1].iov_len = strlen(key) ;
vec[i+2].iov_base = &vec[i+3].iov_len ;
vec[i+2].iov_len = 2 ;
vec[i+3].iov_base = value ;
vec[i+3].iov_len = strlen(value) ;
#endif
#if APR_IS_BIGENDIAN
ptr = (char *) &vec[i+2].iov_len;
vec[i].iov_base = ptr+sizeof(long)-1 ;
vec[i].iov_len = 1 ;
vec[i+1].iov_base = ptr+sizeof(long)-2 ;
vec[i+1].iov_len = 1 ;
#else
vec[i].iov_base = &vec[i+1].iov_len ;
vec[i].iov_len = 2 ;
#endif
#if APR_IS_BIGENDIAN
vec[i+5].iov_base = value ;
vec[i+5].iov_len = strlen(value) ;
#else
vec[i+3].iov_base = value ;
vec[i+3].iov_len = strlen(value) ;
#endif
#if APR_IS_BIGENDIAN
ptr = (char *) &vec[i+5].iov_len;
vec[i+3].iov_base = ptr+sizeof(long)-1 ;
vec[i+3].iov_len = 1 ;
vec[i+4].iov_base = ptr+sizeof(long)-2 ;
vec[i+4].iov_len = 1 ;
#else
vec[i+2].iov_base = &vec[i+3].iov_len ;
vec[i+2].iov_len = 2 ;
#endif
#if APR_IS_BIGENDIAN
*pkt_size+= vec[i+2].iov_len + vec[i+5].iov_len + 4 ;
#else
*pkt_size+= vec[i+1].iov_len + vec[i+3].iov_len + 4 ;
#endif
#if APR_IS_BIGENDIAN
return i+6;
#else
return i+4;
#endif
}
static void *uwsgi_server_config(apr_pool_t *p, server_rec *s) {
@@ -195,12 +243,17 @@ static int uwsgi_handler(request_rec *r) {
uwsgi_cfg *c = ap_get_module_config(r->per_dir_config, &uwsgi_module);
#if APR_IS_BIGENDIAN
struct iovec uwsgi_vars[(MAX_VARS*6)+1] ;
#else
struct iovec uwsgi_vars[(MAX_VARS*4)+1] ;
#endif
int vecptr = 1 ;
char pkt_header[4];
uint16_t pkt_size = 0;
char buf[4096] ;
int cnt,i ;
int i ;
ssize_t cnt ;
const apr_array_header_t *headers;
apr_table_entry_t *h;
char *penv, *cp;
@@ -211,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"))
@@ -234,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);
@@ -270,11 +321,18 @@ 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->args : "", &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REMOTE_USER", r->user ? r->user : "", &pkt_size) ;
if (r->user) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "AUTH_TYPE", (char *) ap_auth_type(r), &pkt_size) ;
}
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "DOCUMENT_ROOT", (char *) ap_document_root(r), &pkt_size) ;
if (c->scheme[0] != 0) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "UWSGI_SCHEME", c->scheme, &pkt_size) ;
}
if (c->script_name[0] == '/') {
if (c->script_name[1] == 0) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", "", &pkt_size) ;
@@ -302,6 +360,7 @@ static int uwsgi_handler(request_rec *r) {
}
}
headers = apr_table_elts(r->headers_in);
h = (apr_table_entry_t *) headers->elts;
@@ -333,13 +392,26 @@ 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;
uwsgi_vars[0].iov_len = 4;
pkt_header[0] = c->modifier1 ;
#if APR_IS_BIGENDIAN
pkt_size = uwsgi_swap16(pkt_size);
memcpy(pkt_header+1, &pkt_size, 2);
pkt_size = uwsgi_swap16(pkt_size);
#else
memcpy(pkt_header+1, &pkt_size, 2);
#endif
pkt_header[3] = c->modifier2 ;
cnt = writev( uwsgi_poll.fd, uwsgi_vars, vecptr );
@@ -354,6 +426,7 @@ static int uwsgi_handler(request_rec *r) {
return HTTP_INTERNAL_SERVER_ERROR;
}
if (ap_should_client_block(r)) {
while ((cnt = ap_get_client_block(r, buf, 4096)) > 0) {
@@ -366,62 +439,92 @@ static int uwsgi_handler(request_rec *r) {
}
}
if (!c->cgi_mode) {
r->assbackwards = 1 ;
uwsgi_http_status[13] = 0 ;
uwsgi_http_status[12] = 0 ;
}
bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
uwsgi_poll.events = POLLIN ;
for(;;) {
/* put -1 to disable timeout on zero */
cnt = poll(&uwsgi_poll, 1, (c->socket_timeout*1000)-1) ;
if (cnt == 0) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() timeout");
break;
apr_brigade_destroy(bb);
return HTTP_INTERNAL_SERVER_ERROR;
}
else if (cnt > 0) {
cnt = recv(uwsgi_poll.fd, buf, 4096, 0) ;
if (cnt > 0) {
if (!c->cgi_mode && uwsgi_http_status_read < 12) {
if (uwsgi_http_status_read + cnt >= 12) {
memcpy(uwsgi_http_status+uwsgi_http_status_read, buf, 12-uwsgi_http_status_read);
r->status = atoi(uwsgi_http_status+8);
uwsgi_http_status_read+=cnt;
}
else {
memcpy(uwsgi_http_status+uwsgi_http_status_read, buf, cnt);
uwsgi_http_status_read+=cnt;
}
}
apr_brigade_write(bb, NULL, NULL, buf, cnt);
}
else if (cnt == 0) {
break;
}
else {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() %s", strerror(errno));
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));
break;
close(uwsgi_poll.fd);
apr_brigade_destroy(bb);
return HTTP_INTERNAL_SERVER_ERROR;
}
}
close(uwsgi_poll.fd);
b = apr_bucket_eos_create(r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
if (!c->cgi_mode) {
if (uwsgi_http_status_read == 0) {
return HTTP_INTERNAL_SERVER_ERROR;
}
}
else {
b = apr_bucket_eos_create(r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
if (hret = ap_scan_script_header_err_brigade(r, bb, NULL)) {
apr_brigade_destroy(bb);
@@ -429,7 +532,8 @@ static int uwsgi_handler(request_rec *r) {
}
}
return ap_pass_brigade(r->output_filters, bb);
return ap_pass_brigade(r->output_filters, bb) ;
}
static const char * cmd_uwsgi_force_script_name(cmd_parms *cmd, void *cfg, const char *location) {
@@ -446,6 +550,20 @@ static const char * cmd_uwsgi_force_script_name(cmd_parms *cmd, void *cfg, const
}
static const char * cmd_uwsgi_force_wsgi_scheme(cmd_parms *cmd, void *cfg, const char *scheme) {
uwsgi_cfg *c = cfg;
if (strlen(scheme) < 9 & strlen(scheme) > 0) {
strcpy(c->scheme, scheme);
}
else {
return "ignored uWSGIforceWSGIscheme. Invalid size (max 8 chars)" ;
}
return NULL ;
}
static const char * cmd_uwsgi_modifier1(cmd_parms *cmd, void *cfg, const char *value) {
uwsgi_cfg *c ;
@@ -588,6 +706,7 @@ static const command_rec uwsgi_cmds[] = {
AP_INIT_TAKE1("uWSGImodifier2", cmd_uwsgi_modifier2, NULL, RSRC_CONF|ACCESS_CONF, "Set uWSGI modifier2"),
AP_INIT_TAKE1("uWSGIforceScriptName", cmd_uwsgi_force_script_name, NULL, ACCESS_CONF, "Fix for PATH_INFO/SCRIPT_NAME when the location has filesystem correspondence"),
AP_INIT_TAKE1("uWSGIforceCGImode", cmd_uwsgi_force_cgi_mode, NULL, ACCESS_CONF, "Force uWSGI CGI mode for perfect integration with apache filter"),
AP_INIT_TAKE1("uWSGIforceWSGIscheme", cmd_uwsgi_force_wsgi_scheme, NULL, ACCESS_CONF, "Force the WSGI scheme var (set by default to \"http\")"),
{NULL}
};
+368
View File
@@ -0,0 +1,368 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
struct wsgi_request *find_wsgi_req_by_fd(int fd) {
return uwsgi.async_waiting_fd_table[fd];
}
void runqueue_remove(struct uwsgi_async_request *u_request) {
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 (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 {
wsgi_req->waiting_fds = uad;
}
if (timeout > 0) {
async_add_timeout(wsgi_req, timeout);
}
uwsgi.async_waiting_fd_table[fd] = wsgi_req;
event_queue_add_fd_read(uwsgi.async_queue, fd);
}
void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
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);
}
}
void async_add_fd_write(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_write();
uad->prev = last_uad;
uad->next = NULL;
if (last_uad) {
last_uad->next = uad;
}
else {
wsgi_req->waiting_fds = uad;
}
if (timeout > 0) {
async_add_timeout(wsgi_req, timeout);
}
uwsgi.async_waiting_fd_table[fd] = wsgi_req;
event_queue_add_fd_write(uwsgi.async_queue, fd);
}
void async_schedule_to_req(void) {
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->request(uwsgi.wsgi_req);
}
void *async_loop(void *arg1) {
struct uwsgi_async_fd *tmp_uaf;
int interesting_fd, i;
struct uwsgi_rb_timer *min_timeout;
int timeout;
static struct uwsgi_async_request *current_request = NULL, *next_async_request = NULL;
void *events = event_queue_alloc(64);
uwsgi.async_runqueue = NULL;
uwsgi.async_runqueue_cnt = 0;
// set a default request manager
if (!uwsgi.schedule_to_req) uwsgi.schedule_to_req = async_schedule_to_req;
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
if (uwsgi.async_runqueue_cnt) {
timeout = 0;
}
else {
min_timeout = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts);
if (uwsgi.async_runqueue_cnt) {
timeout = 0;
}
if (min_timeout) {
timeout = min_timeout->key - time(NULL);
if (timeout <= 0) {
async_expire_timeouts();
timeout = 0;
}
}
else {
timeout = -1;
}
}
uwsgi.async_nevents = event_queue_wait_multi(uwsgi.async_queue, timeout, events, 64);
// timeout ???
if (uwsgi.async_nevents == 0) {
async_expire_timeouts();
}
for(i=0;i<uwsgi.async_nevents;i++) {
// manage events
interesting_fd = event_queue_interesting_fd(events, i);
// 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_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);
}
}
// 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();
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;
}
-25
View File
@@ -1,25 +0,0 @@
all: clean uwsgi
uwsgi: utils.o protocol.o socket.o pymodule.o spooler.o main.o
$(CC) $(LD_FLAGS) utils.o protocol.o socket.o spooler.o pymodule.o main.o -o $(PROGRAM)
utils.o: utils.c
$(CC) -c $(CFLAGS) utils.c
protocol.o: protocol.c
$(CC) -c $(CFLAGS) protocol.c
socket.o: socket.c
$(CC) -c $(CFLAGS) socket.c
spooler.o: spooler.c
$(CC) -c $(CFLAGS) spooler.c
pymodule.o: uwsgi_pymodule.c
$(CC) -c $(CFLAGS) -o pymodule.o uwsgi_pymodule.c
main.o: uwsgi.c
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
clean:
rm -f utils.o protocol.o socket.o pymodule.o spooler.o main.o
+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
+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 =
+4
View File
@@ -0,0 +1,4 @@
[uwsgi]
inherit = unbit
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,
};
+1
View File
@@ -0,0 +1 @@
the uwsgi handler is included in the official Cherokee distribution
-92
View File
@@ -1,92 +0,0 @@
from Form import *
from Table import *
from Module import *
from validations import *
from consts import *
# For gettext
N_ = lambda x: x
from ModuleCgi import *
from ModuleBalancer import NOTE_BALANCER
HELPS = [
('modules_handlers_uwsgi', "UWSGI")
]
class ModuleUwsgi (ModuleCgiBase):
PROPERTIES = ModuleCgiBase.PROPERTIES + [
'balancer',
'modifier1',
'modifier2',
'pass_wsgi_vars',
'pass_request_body'
]
def __init__ (self, cfg, prefix, submit):
ModuleCgiBase.__init__ (self, cfg, prefix, 'uwsgi', submit)
self.show_script_alias = False
self.show_change_uid = False
self.show_document_root = True
def _op_render (self):
txt = ModuleCgiBase._op_render (self)
txt += '<h2>%s</h2>' % (_('UWSGI specific'))
table = TableProps()
opt = "%s!modifier1" % (self._prefix)
self.AddPropEntry(table, _('Modifier1'), opt, 'a number between 0 and 255', size=3);
opt = "%s!modifier2" % (self._prefix)
self.AddPropEntry(table, _('Modifier2'), opt, 'a number between 0 and 255', size=3);
opt = "%s!pass_wsgi_vars" % (self._prefix)
self.AddPropCheck (table, _("Pass WSGI vars"), opt, True, 'pass all the wsgi vars to the application')
opt = "%s!pass_request_body" % (self._prefix)
self.AddPropCheck (table, _("Pass Request body"), opt, True, 'pass the request body to the application')
opt = "%s!balancer" % (self._prefix)
e = self.AddPropOptions_Reload_Module (table, _("Balancer"), opt,
modules_available(BALANCERS), _(NOTE_BALANCER))
txt += self.Indent(str(table) + e)
return txt
def _op_apply_changes (self, uri, post):
# Apply modifier1
opt = "%s!modifier1" % (self._prefix)
mod1 = post.pop(opt)
if mod1:
self._cfg[opt] = mod1
# Apply modifier2
opt = "%s!modifier2" % (self._prefix)
mod2 = post.pop(opt)
if mod2:
self._cfg[opt] = mod2
# Apply pass_request_body and pass_wsgi_vars
self.ApplyChangesPrefix (self._prefix, ['pass_wsgi_vars','pass_request_body'], post)
# Apply balancer changes
pre = "%s!balancer" % (self._prefix)
new_balancer = post.pop(pre)
if new_balancer:
self._cfg[pre] = new_balancer
cfg = self._cfg[pre]
if cfg and cfg.value:
name = cfg.value
props = module_obj_factory (name, self._cfg, pre, self.submit_url)
props._op_apply_changes (uri, post)
# And CGI changes
return ModuleCgiBase._op_apply_changes (self, uri, post)
-452
View File
@@ -1,452 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* Cherokee
*
* Authors:
* Alvaro Lopez Ortega <alvaro@alobbs.com>
*
* Copyright (C) 2001-2009 Alvaro Lopez Ortega
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*
* 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.
*/
#include "common-internal.h"
#include "handler_uwsgi.h"
#include "connection.h"
#include "source_interpreter.h"
#include "thread.h"
#include "util.h"
#include "connection-protected.h"
#include "bogotime.h"
#define ENTRIES "handler,cgi"
/* Plug-in initialization
*/
CGI_LIB_INIT (uwsgi, http_all_methods);
#if BYTE_ORDER == BIG_ENDIAN
static uint16_t uwsgi_swap16(uint16_t x) {
return (uint16_t) ((x & 0xff) << 8 | (x & 0xff00) >> 8);
}
#endif
/* Methods implementation
*/
static ret_t
props_free (cherokee_handler_uwsgi_props_t *props)
{
if (props->balancer)
cherokee_balancer_free (props->balancer);
return cherokee_handler_cgi_base_props_free (PROP_CGI_BASE(props));
}
ret_t
cherokee_handler_uwsgi_configure (cherokee_config_node_t *conf, cherokee_server_t *srv, cherokee_module_props_t **_props)
{
ret_t ret;
cherokee_list_t *i;
cherokee_handler_uwsgi_props_t *props;
/* Instance a new property object
*/
if (*_props == NULL) {
CHEROKEE_NEW_STRUCT (n, handler_uwsgi_props);
cherokee_handler_cgi_base_props_init_base (PROP_CGI_BASE(n),
MODULE_PROPS_FREE(props_free));
n->balancer = NULL;
n->modifier1 = 0 ;
n->modifier2 = 0 ;
n->pass_wsgi_vars = true;
n->pass_request_body = true;
*_props = MODULE_PROPS(n);
}
props = PROP_UWSGI(*_props);
/* Parse the configuration tree
*/
cherokee_config_node_foreach (i, conf) {
cherokee_config_node_t *subconf = CONFIG_NODE(i);
if (equal_buf_str (&subconf->key, "balancer")) {
ret = cherokee_balancer_instance (&subconf->val, subconf, srv, &props->balancer);
if (ret != ret_ok) return ret;
}
else if (equal_buf_str (&subconf->key, "modifier1")) {
props->modifier1 = (uint8_t) atoi(subconf->val.buf);
}
else if (equal_buf_str (&subconf->key, "modifier2")) {
props->modifier2 = (uint8_t) atoi(subconf->val.buf);
}
else if (equal_buf_str (&subconf->key, "pass_wsgi_vars")) {
props->pass_wsgi_vars = !! atoi (subconf->val.buf);
}
else if (equal_buf_str (&subconf->key, "pass_request_body")) {
props->pass_request_body = !! atoi (subconf->val.buf);
}
}
/* Init base class
*/
ret = cherokee_handler_cgi_base_configure (conf, srv, _props);
if (ret != ret_ok) return ret;
/* Final checks
*/
if (props->balancer == NULL) {
LOG_CRITICAL_S (CHEROKEE_ERROR_HANDLER_NO_BALANCER);
return ret_error;
}
return ret_ok;
}
static void
add_env_pair (cherokee_handler_cgi_base_t *cgi_base,
const char *key, int key_len,
const char *val, int val_len)
{
cherokee_handler_uwsgi_t *uwsgi = HDL_UWSGI(cgi_base);
uint16_t u_key_len = (uint16_t) key_len ;
uint16_t u_val_len = (uint16_t) val_len ;
/* 2 bytes for every string (16 bit le) */
cherokee_buffer_ensure_size (&uwsgi->header, uwsgi->header.len + key_len + val_len + 4);
/* force to le if cherokee is big-endian */
#if BYTE_ORDER == BIG_ENDIAN
u_key_len = uwsgi_swap16(u_key_len);
#endif
cherokee_buffer_add (&uwsgi->header, (const char *) &u_key_len, 2);
#if BYTE_ORDER == BIG_ENDIAN
u_key_len = uwsgi_swap16(u_key_len);
#endif
cherokee_buffer_add (&uwsgi->header, key, key_len);
#if BYTE_ORDER == BIG_ENDIAN
u_val_len = uwsgi_swap16(u_val_len);
#endif
cherokee_buffer_add (&uwsgi->header, (const char *) &u_val_len, 2);
#if BYTE_ORDER == BIG_ENDIAN
u_val_len = uwsgi_swap16(u_val_len);
#endif
cherokee_buffer_add (&uwsgi->header, val, val_len);
}
static ret_t
read_from_uwsgi (cherokee_handler_cgi_base_t *cgi_base, cherokee_buffer_t *buffer)
{
ret_t ret;
size_t read = 0;
cherokee_handler_uwsgi_t *uwsgi = HDL_UWSGI(cgi_base);
ret = cherokee_socket_bufread (&uwsgi->socket, buffer, 4096, &read);
switch (ret) {
case ret_eagain:
cherokee_thread_deactive_to_polling (HANDLER_THREAD(cgi_base), HANDLER_CONN(cgi_base),
uwsgi->socket.socket, 0, false);
return ret_eagain;
case ret_ok:
TRACE (ENTRIES, "%d bytes read\n", read);
return ret_ok;
case ret_eof:
case ret_error:
cgi_base->got_eof = true;
return ret;
default:
RET_UNKNOWN(ret);
}
SHOULDNT_HAPPEN;
return ret_error;
}
ret_t
cherokee_handler_uwsgi_new (cherokee_handler_t **hdl, void *cnt, cherokee_module_props_t *props)
{
CHEROKEE_NEW_STRUCT (n, handler_uwsgi);
/* Init the base class
*/
cherokee_handler_cgi_base_init (
HDL_CGI_BASE(n), cnt,
PLUGIN_INFO_HANDLER_PTR(uwsgi),
HANDLER_PROPS(props),
add_env_pair, read_from_uwsgi);
/* Virtual methods
*/
MODULE(n)->init = (handler_func_init_t) cherokee_handler_uwsgi_init;
MODULE(n)->free = (module_func_free_t) cherokee_handler_uwsgi_free;
/* Virtual methods: implemented by handler_cgi_base
*/
HANDLER(n)->step = (handler_func_step_t) cherokee_handler_cgi_base_step;
HANDLER(n)->add_headers = (handler_func_add_headers_t) cherokee_handler_cgi_base_add_headers;
/* Properties
*/
n->post_len = 0;
n->src_ref = NULL;
cherokee_buffer_init (&n->header);
cherokee_socket_init (&n->socket);
/* Return the object
*/
*hdl = HANDLER(n);
return ret_ok;
}
ret_t
cherokee_handler_uwsgi_free (cherokee_handler_uwsgi_t *hdl)
{
/* Free the rest of the handler CGI memory
*/
cherokee_handler_cgi_base_free (HDL_CGI_BASE(hdl));
/* UWSGI stuff
*/
cherokee_socket_close (&hdl->socket);
cherokee_socket_mrproper (&hdl->socket);
cherokee_buffer_mrproper (&hdl->header);
return ret_ok;
}
static ret_t
uwsgi_fix_packet (cherokee_buffer_t *buf, uint8_t modifier1, uint8_t modifier2)
{
uwsgi_header uh;
uh.modifier1 = modifier1 ;
uh.modifier2 = modifier2 ;
#if BYTE_ORDER == BIG_ENDIAN
uh.env_size = uwsgi_swap16((uint16_t) buf->len) ;
#else
uh.env_size = (uint16_t) buf->len ;
#endif
cherokee_buffer_ensure_size (buf, buf->len + 4);
cherokee_buffer_prepend (buf, (const char * )&uh, 4);
return ret_ok;
}
static ret_t
build_header (cherokee_handler_uwsgi_t *hdl)
{
cherokee_handler_uwsgi_props_t *props = HANDLER_UWSGI_PROPS(hdl);
cuint_t len;
char tmp[64];
if (props->pass_request_body == true && props->pass_wsgi_vars == true) {
len = snprintf (tmp, sizeof(tmp), FMT_OFFSET, (CST_OFFSET)hdl->post_len);
add_env_pair(HDL_CGI_BASE(hdl), "CONTENT_LENGTH", 14, tmp, len);
}
if (props->pass_wsgi_vars == true) {
cherokee_handler_cgi_base_build_envp (HDL_CGI_BASE(hdl), HANDLER_CONN(hdl));
}
return uwsgi_fix_packet (&hdl->header, props->modifier1, props->modifier2);
}
static ret_t
connect_to_server (cherokee_handler_uwsgi_t *hdl)
{
ret_t ret;
cherokee_connection_t *conn = HANDLER_CONN(hdl);
cherokee_handler_uwsgi_props_t *props = HANDLER_UWSGI_PROPS(hdl);
/* Get a reference to the target host
*/
if (hdl->src_ref == NULL) {
ret = cherokee_balancer_dispatch (props->balancer, conn, &hdl->src_ref);
if (ret != ret_ok)
return ret;
}
/* Try to connect
*/
if (hdl->src_ref->type == source_host) {
ret = cherokee_source_connect_polling (hdl->src_ref, &hdl->socket, conn);
if ((ret == ret_deny) || (ret == ret_error))
{
cherokee_balancer_report_fail (props->balancer, conn, hdl->src_ref);
}
} else {
ret = cherokee_source_interpreter_connect_polling (SOURCE_INT(hdl->src_ref),
&hdl->socket, conn);
}
return ret;
}
static ret_t
send_header (cherokee_handler_uwsgi_t *hdl)
{
ret_t ret;
size_t written = 0;
cherokee_connection_t *conn = HANDLER_CONN(hdl);
ret = cherokee_socket_bufwrite (&hdl->socket, &hdl->header, &written);
if (ret != ret_ok) {
conn->error_code = http_bad_gateway;
return ret;
}
#if 0
cherokee_buffer_print_debug (&hdl->header, -1);
#endif
cherokee_buffer_move_to_begin (&hdl->header, written);
TRACE (ENTRIES, "sent remaining=%d\n", hdl->header.len);
if (! cherokee_buffer_is_empty (&hdl->header))
return ret_eagain;
return ret_ok;
}
static ret_t
send_post (cherokee_handler_uwsgi_t *hdl)
{
ret_t ret;
int e_fd = -1;
int mode = 0;
cherokee_connection_t *conn = HANDLER_CONN(hdl);
ret = cherokee_post_walk_to_fd (&conn->post, hdl->socket.socket, &e_fd, &mode);
switch (ret) {
case ret_ok:
break;
case ret_eagain:
if (e_fd != -1)
cherokee_thread_deactive_to_polling (HANDLER_THREAD(hdl), conn, e_fd, mode, false);
return ret_eagain;
default:
conn->error_code = http_bad_gateway;
return ret;
}
return ret_ok;
}
ret_t
cherokee_handler_uwsgi_init (cherokee_handler_uwsgi_t *hdl)
{
ret_t ret;
cherokee_connection_t *conn = HANDLER_CONN(hdl);
cherokee_handler_uwsgi_props_t *props = HANDLER_UWSGI_PROPS(hdl);
switch (HDL_CGI_BASE(hdl)->init_phase) {
case hcgi_phase_build_headers:
TRACE (ENTRIES, "Init: %s\n", "begins");
/* Extracts PATH_INFO and filename from request uri
*/
ret = cherokee_handler_cgi_base_extract_path (HDL_CGI_BASE(hdl), false);
if (unlikely (ret < ret_ok)) {
conn->error_code = http_internal_error;
return ret_error;
}
/* Prepare Post
*/
if (! cherokee_post_is_empty (&conn->post)) {
cherokee_post_walk_reset (&conn->post);
cherokee_post_get_len (&conn->post, &hdl->post_len);
}
/* Build the headers
*/
ret = build_header (hdl);
if (unlikely (ret != ret_ok)) {
conn->error_code = http_internal_error;
return ret_error;
}
HDL_CGI_BASE(hdl)->init_phase = hcgi_phase_connect;
case hcgi_phase_connect:
TRACE (ENTRIES, "Init: %s\n", "connect");
/* Connect
*/
ret = connect_to_server (hdl);
switch (ret) {
case ret_ok:
break;
case ret_eagain:
return ret_eagain;
case ret_deny:
conn->error_code = http_gateway_timeout;
return ret_error;
default:
conn->error_code = http_service_unavailable;
return ret_error;
}
HDL_CGI_BASE(hdl)->init_phase = hcgi_phase_send_headers;
case hcgi_phase_send_headers:
TRACE (ENTRIES, "Init: %s\n", "send_headers");
/* Send the header
*/
ret = send_header (hdl);
if (ret != ret_ok)
return ret;
HDL_CGI_BASE(hdl)->init_phase = hcgi_phase_send_post;
case hcgi_phase_send_post:
/* Send the Post
*/
if (hdl->post_len > 0 && props->pass_request_body == true) {
return send_post (hdl);
}
break;
}
return ret_ok;
}
-78
View File
@@ -1,78 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* Cherokee
*
* Authors:
* Alvaro Lopez Ortega <alvaro@alobbs.com>
*
* Copyright (C) 2001-2009 Alvaro Lopez Ortega
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*
* 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.
*/
#ifndef CHEROKEE_HANDLER_UWSGI_H
#define CHEROKEE_HANDLER_UWSGI_H
#include "common-internal.h"
#include "handler.h"
#include "buffer.h"
#include "plugin_loader.h"
#include "socket.h"
#include "handler_cgi_base.h"
#include "balancer.h"
typedef struct __attribute__((packed)) {
uint8_t modifier1;
uint16_t env_size;
uint8_t modifier2;
} uwsgi_header ;
typedef struct {
cherokee_handler_cgi_base_t base;
cherokee_balancer_t *balancer;
uint8_t modifier1;
uint8_t modifier2;
cherokee_boolean_t pass_wsgi_vars;
cherokee_boolean_t pass_request_body;
} cherokee_handler_uwsgi_props_t;
typedef struct {
cherokee_handler_cgi_base_t base;
cherokee_buffer_t header;
cherokee_socket_t socket;
cherokee_source_t *src_ref;
time_t spawned;
off_t post_len;
} cherokee_handler_uwsgi_t;
#define HDL_UWSGI(x) ((cherokee_handler_uwsgi_t *)(x))
#define PROP_UWSGI(x) ((cherokee_handler_uwsgi_props_t *)(x))
#define HANDLER_UWSGI_PROPS(x) (PROP_UWSGI(MODULE(x)->props))
/* Library init function
*/
void PLUGIN_INIT_NAME(uwsgi) (cherokee_plugin_loader_t *loader);
/* Methods
*/
ret_t cherokee_handler_uwsgi_new (cherokee_handler_t **hdl, void *cnt, cherokee_module_props_t *props);
ret_t cherokee_handler_uwsgi_free (cherokee_handler_uwsgi_t *hdl);
ret_t cherokee_handler_uwsgi_init (cherokee_handler_uwsgi_t *hdl);
#endif /* CHEROKEE_HANDLER_UWSGI_H */
-1
View File
@@ -1 +0,0 @@
file
+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
+144
View File
@@ -0,0 +1,144 @@
package Plack::Handler::Uwsgi;
use strict;
use warnings;
use IO::Socket::INET;
use HTTP::Status;
use Plack::Util;
sub new {
my $class = shift;
my $self = bless {@_}, $class;
$self;
}
sub run {
my ($self, $app) = @_;
my $server;
if (exists($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);
}
while ( my $client = $server->accept ) {
my $head = '';
my $remains = 4;
while($remains) {
$client->recv(my $buf, $remains);
last unless $buf;
$head.=$buf;
$remains -= length($buf);
}
if (length($head) != 4) {
$client->close;
next;
}
my ($mod1, $envsize, $mod2) = unpack('CvC', $head);
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);
}
unless($buf) {
$client->close;
next;
}
$envbuf.=$buf;
$remains -= length($buf);
}
if (length($envbuf) != $envsize ) {
$client->close;
next;
}
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 $env = {
%env,
'psgi.version' => [1,1],
'psgi.url_scheme' => ($env{HTTPS}||'off') =~ /^(?:on|1)$/i ? 'https' : 'http',
'psgi.input' => $client,
'psgi.errors' => *STDERR,
'psgi.multithread' => Plack::Util::FALSE,
'psgi.multiprocess' => Plack::Util::TRUE,
'psgi.run_once' => Plack::Util::FALSE,
'psgi.streaming' => Plack::Util::TRUE,
'psgi.nonblocking' => Plack::Util::FALSE,
};
my $res = Plack::Util::run_app $app, $env;
if (ref $res eq 'ARRAY') {
$self->_handle_response($client, $env{'SERVER_PROTOCOL'}, $res);
}
elsif (ref $res eq 'CODE') {
$res->(sub {
$self->_handle_response($client, $env{'SERVER_PROTOCOL'}, $_[0]);
});
}
else {
die "Bad response $res";
}
$client->close;
}
}
sub _handle_response {
my ($self, $client, $protocol, $res) = @_;
$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";
$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 { };
}
}
1;
View File
+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
+330
View File
@@ -0,0 +1,330 @@
require 'rubygems'
require 'socket'
require 'rack'
require 'rack/content_length'
require 'rack/rewindable_input'
require 'stringio'
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
$requests = 0
$workers = Array.new
$mywid = 0
module Rack
class RailsCachingHack
def initialize app
@app = app
end
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
module Handler
class Unbit
def self.run(app, options={})
server = UNIXServer.for_fd(0)
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
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')
starttime = Time.now
app = nil
if options[:config]
cfgfile = File.read(options[:config])
if cfgfile[/^#\\(.*)/]
opts.parse! $1.split(/\s+/)
end
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 'config/environment'
end
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
ulog("your app is ready (in #{Time.now-starttime} seconds).")
server.run(app, options)
View File
+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);
}
}
+150
View File
@@ -0,0 +1,150 @@
require 'socket'
require 'rack/content_length'
require 'rack/rewindable_input'
require 'stringio'
module Rack
module Handler
class Uwsgi
def self.run(app, options={})
if ENV['UWSGI_FD']
server = UNIXServer.for_fd(ENV['UWSGI_FD'].to_i)
else
server = TCPServer.new(options[:Host], options[:Port])
end
while client = server.accept
serve client, app
end
end
def self.serve(client, app)
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_uwsgi_Input')
rack_input.chmod(0000)
rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding)
rack_input.binmode
if RUBY_PLATFORM !~ /(mswin|mingw|cygwin|java)/
rack_input.unlink
end
remains = env["CONTENT_LENGTH"].to_i
while remains > 0
if remains >= 4096
buf, sender = client.recvfrom(4096)
else
buf, sender = client.recvfrom(remains)
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)
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
ensure
rack_input.close
client.close
end
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
+96
View File
@@ -0,0 +1,96 @@
/*
*** uWSGI cgi client ***
to compile:
gcc -Wall -o uwsgi_client.cgi uwsgi_client.c
*/
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#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;
char *content_length;
memset(&s_addr, 0, sizeof(struct sockaddr_un));
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);
}
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);
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 (res == mptr-message) {
while( (res = recv(uwsgi_socket, message, 4096,0)) ) {
write(1, message, res);
}
}
return 0;
}
+95
View File
@@ -0,0 +1,95 @@
/*
*** uWSGI cgi client ***
to compile:
gcc -Wall -o uwsgi_client.cgi uwsgi_dynamic_client.c
*/
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#define UWSGI_SOCK "/tmp/uwsgi.sock"
#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;
memset(&s_addr, 0, sizeof(struct sockaddr_un));
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);
}
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);
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++;
}
}
message[0] = 0;
len = (mptr-message)-4;
memcpy(message+1, &len, 2);
message[3] = 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;
}
-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
View File
+90
View File
@@ -0,0 +1,90 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="../">{% trans 'Home' %}</a> &rsaquo;
{% trans 'uWSGI' %}
</div>
{% endblock %}
{% block content %}
<div id="content-main">
<h1>uWSGI status</h1>
<b>masterpid:</b> {{masterpid}}<br/>
<b>started_on:</b> {{started_on}}<br/>
<b>buffer size:</b> {{buffer_size}}<br/>
<b>workers:</b> {{numproc}}<br/>
<b>total requests:</b> {{total_requests}}<br/>
<br/>
<div class="module" style="width:860px">
<table>
<caption style="width:860px">workers</caption>
<thead>
<tr>
<th scope="row">id</th>
<th scope="row">pid</th>
<th scope="row">requests</th>
<th scope="row">running time (milliseconds)</th>
<th scope="row">load</th>
<th scope="row">last spawn</th>
<th scope="row">respawn count</th>
<th scope="row">address space (vsz)</th>
<th scope="row">resident memory (rss)</th>
</tr>
</thead>
<tbody>
{% for w in workers %}
<tr>
<td align="center">{{w.id}}</td>
<td align="center">{{w.pid}}</td>
<td align="right">{{w.requests}}</td>
<td align="right">{{w.running_time}}</td>
<td align="right">{{w.load|floatformat:2}} %</td>
<td align="right">{{w.last_spawn_str}}</td>
<td align="right">{{w.respawn_count}}</td>
<td align="right">{{w.vsz|filesizeformat}}</td>
<td align="right">{{w.rss|filesizeformat}}</td>
</tr>
{% endfor %}
</tbody>
</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 %}
</div>
{% endblock %}
+10
View File
@@ -0,0 +1,10 @@
import sys, os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from django.conf.urls.defaults import *
urlpatterns = patterns('uwsgi_admin.views',
(r'^$', 'index'),
(r'^reload/$', 'reload')
)
+41
View File
@@ -0,0 +1,41 @@
import uwsgi
import time
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.contrib.admin.views.decorators import staff_member_required
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
def index(request):
workers = uwsgi.workers()
total_load = time.time() - uwsgi.started_on
for w in workers:
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)
def reload(request):
if uwsgi.masterpid() > 0:
uwsgi.reload()
request.user.message_set.create(message="uWSGI reloaded")
else:
request.user.message_set.create(message="The uWSGI master process is not active")
return HttpResponseRedirect(reverse(index))
reload = staff_member_required(reload)
+348
View File
@@ -0,0 +1,348 @@
#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 pipe[2];
};
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]);
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 (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) {
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));
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;
}
// 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]);
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);
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]);
// 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;
memset(&ui_base, 0, sizeof(struct uwsgi_instance));
uwsgi_log("*** starting uWSGI Emperor ***\n");
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 (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);
}
}
}
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);
}
}
}
}
// 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 {
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->pid == diedpid) {
if (ui_current->status == 0) {
// respawn an accidentally dead instance
emperor_add(ui_current->name, ui_current->last_mod);
emperor_del(ui_current);
break;
}
else if (ui_current->status == 1) {
// remove 'marked for dead' instance
emperor_del(ui_current);
break;
}
}
else if (ui_current->status == 1) {
emperor_del(ui_current);
break;
}
else if (stat(ui_current->name, &st)) {
emperor_stop(ui_current);
}
}
sleep(3);
}
}
+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
+31
View File
@@ -0,0 +1,31 @@
import uwsgi
import time
import rrdtool
# rrdtool create test.rrd --start 1270879004 -s 10 DS:requests:COUNTER:300:U:U RRA:AVERAGE:0.5:3:105120
s_freq = 10
# 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.register_timer(0, s_freq, uwsgi.KIND_WORKER, rrdtool_updater)
def hello_world(env, start_response):
start_response('200 Ok', [('Content-type', 'text/plain')])
return 'Hello world !'
def graph(env, start_response):
start_response('200 Ok', [('Content-type', 'image/png')])
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')
# 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
+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;
}
+326 -280
View File
@@ -35,6 +35,23 @@
#define data_uwsgi data_fastcgi
#define data_uwsgi_init data_fastcgi_init
#ifdef __linux__
#include <endian.h>
#elif __sun__
#elif __APPLE__
#include <libkern/OSByteOrder.h>
#else
#include <machine/endian.h>
#endif
#ifdef __BIG_ENDIAN__
static uint16_t uwsgi_swap16(uint16_t x) {
return (uint16_t) ((x & 0xff) << 8 | (x & 0xff00) >> 8);
}
#endif
/**
*
* the uwsgi module is based on the proxy module
@@ -47,25 +64,17 @@ typedef struct __attribute__((packed)) {
uint8_t modifier1;
uint16_t pktsize;
uint8_t modifier2;
} uwsgi_header ;
typedef enum {
UWSGI_BALANCE_UNSET,
UWSGI_BALANCE_FAIR,
} uwsgi_balance_t;
} uwsgi_header;
typedef struct {
array *extensions;
unsigned short debug;
uwsgi_balance_t balance;
} plugin_config;
typedef struct {
PLUGIN_DATA;
buffer *parse_response;
buffer *balance_buf;
plugin_config **config_storage;
@@ -121,6 +130,7 @@ static handler_ctx * handler_ctx_init() {
hctx->fd = -1;
hctx->fde_ndx = -1;
return hctx;
}
@@ -138,7 +148,6 @@ INIT_FUNC(mod_uwsgi_init) {
p = calloc(1, sizeof(*p));
p->parse_response = buffer_init();
p->balance_buf = buffer_init();
return p;
}
@@ -150,7 +159,6 @@ FREE_FUNC(mod_uwsgi_free) {
UNUSED(srv);
buffer_free(p->parse_response);
buffer_free(p->balance_buf);
if (p->config_storage) {
size_t i;
@@ -180,7 +188,6 @@ SETDEFAULTS_FUNC(mod_uwsgi_set_defaults) {
config_values_t cv[] = {
{ "uwsgi.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
{ "uwsgi.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
{ "uwsgi.balance", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
{ NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
};
@@ -196,9 +203,7 @@ SETDEFAULTS_FUNC(mod_uwsgi_set_defaults) {
cv[0].destination = s->extensions;
cv[1].destination = &(s->debug);
cv[2].destination = p->balance_buf;
buffer_reset(p->balance_buf);
p->config_storage[i] = s;
ca = ((data_config *)srv->config_context->data[i])->value;
@@ -207,16 +212,6 @@ SETDEFAULTS_FUNC(mod_uwsgi_set_defaults) {
return HANDLER_ERROR;
}
if (buffer_is_empty(p->balance_buf)) {
s->balance = UWSGI_BALANCE_FAIR;
} else if (buffer_is_equal_string(p->balance_buf, CONST_STR_LEN("fair"))) {
s->balance = UWSGI_BALANCE_FAIR;
} else {
log_error_write(srv, __FILE__, __LINE__, "s",
"uwsgi.balance has to be fair");
return HANDLER_ERROR;
}
if (NULL != (du = array_get_element(ca, "uwsgi.server"))) {
size_t j;
data_array *da = (data_array *)du;
@@ -276,7 +271,7 @@ SETDEFAULTS_FUNC(mod_uwsgi_set_defaults) {
df = data_uwsgi_init();
df->port = 80;
df->port = 3031;
buffer_copy_string_buffer(df->key, da_host->key);
@@ -396,17 +391,33 @@ static int uwsgi_establish_connection(server *srv, handler_ctx *hctx) {
return 0;
}
static void uwsgi_add_var(buffer *b, char * key, uint16_t keylen, char *val, uint16_t vallen) {
#ifdef __BIG_ENDIAN__
uint16_t uwlen;
uwlen = uwsgi_swap16(keylen);
buffer_append_memory(b, (char *) &uwlen, 2); buffer_append_memory(b, key, keylen);
uwlen = uwsgi_swap16(vallen);
buffer_append_memory(b, (char *) &uwlen, 2); buffer_append_memory(b, val, vallen);
#else
buffer_append_memory(b, (char *) &keylen, 2); buffer_append_memory(b, key, keylen);
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 ;
uint16_t uwsgi_strsize;
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;
@@ -416,93 +427,138 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
b = chunkqueue_get_append_buffer(hctx->wb);
log_error_write(srv, __FILE__, __LINE__, "s", "starting uwsgi request...");
/* make space for uwsgi header */
buffer_append_memory(b, "\0\0\0\0", 4);
log_error_write(srv, __FILE__, __LINE__, "s", "space done...");
/* set WSGI vars */
s = get_http_method_name(con->request.http_method);
uwsgi_strsize = 14; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, "REQUEST_METHOD", uwsgi_strsize);
uwsgi_strsize = strlen(s); buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, s, uwsgi_strsize);
uwsgi_add_var(b, "REQUEST_METHOD", 14, (char *) s, strlen(s));
uwsgi_strsize = 12; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, "QUERY_STRING", uwsgi_strsize);
if (!buffer_is_empty(con->uri.query)) {
uwsgi_strsize = con->uri.query->used; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, con->uri.query->ptr, uwsgi_strsize);
} else {
uwsgi_strsize = 0; buffer_append_memory(b, &uwsgi_strsize, 2);
}
uwsgi_add_var(b, "QUERY_STRING", 12, con->uri.query->ptr, con->uri.query->used-1);
} else {
uwsgi_add_var(b, "QUERY_STRING", 12, "", 0);
}
s = get_http_version_name(con->request.http_version);
uwsgi_strsize = 15; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, "SERVER_PROTOCOL", uwsgi_strsize);
uwsgi_strsize = strlen(s); buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, s, uwsgi_strsize);
uwsgi_add_var(b, "SERVER_PROTOCOL", 15, (char *) s, strlen(s));
uwsgi_strsize = 11; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, "SERVER_NAME", uwsgi_strsize);
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;
uwsgi_strsize = len ;
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_strsize = strlen(s);
}
buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, s, uwsgi_strsize);
uwsgi_add_var(b, "SERVER_NAME", 11, (char *)s, strlen(s));
}
uwsgi_strsize = 11; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, "SERVER_PORT", uwsgi_strsize);
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_strsize = strlen(s); buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, s, uwsgi_strsize);
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);
uwsgi_strsize = 11; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, "REQUEST_URI", uwsgi_strsize);
uwsgi_strsize = con->request.orig_uri->used; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, con->request.orig_uri->ptr, uwsgi_strsize);
uwsgi_strsize = 11; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, "REMOTE_PORT", uwsgi_strsize);
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));
}
uwsgi_strsize = strlen(s); buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, s, uwsgi_strsize);
uwsgi_strsize = 11; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, "REMOTE_ADDR", uwsgi_strsize);
s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
uwsgi_strsize = strlen(s); buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, s, uwsgi_strsize);
uwsgi_add_var(b, "REMOTE_ADDR", 11, (char *)s, strlen(s));
uh = (uwsgi_header *) b->ptr ;
uh->modifier1 = 0 ;
uh->pktsize = b->used - 4 ;
uh->modifier2 = 0 ;
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->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->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];
if (ds->value->used && ds->key->used) {
size_t j;
buffer_reset(srv->tmp_buf);
if (!strcasecmp(ds->key->ptr, "CONTENT-TYPE") || !strcasecmp(ds->key->ptr, "CONTENT-LENGTH")) {
buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
}
else {
buffer_prepare_append(srv->tmp_buf, ds->key->used + 7);
buffer_append_memory(srv->tmp_buf, "HTTP_", 5);
}
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);
}
}
for (i = 0; i < con->environment->used; i++) {
data_string *ds;
ds = (data_string *)con->environment->data[i];
if (ds->value->used && ds->key->used) {
size_t j;
buffer_reset(srv->tmp_buf);
buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
for (j = 0; j < ds->key->used - 1; j++) {
srv->tmp_buf->ptr[srv->tmp_buf->used++] = light_isalnum((unsigned char)ds->key->ptr[j]) ? toupper((unsigned char)ds->key->ptr[j]) : '_';
}
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);
}
}
uh = (uwsgi_header *) b->ptr;
uh->modifier1 = (uint8_t) 0;
#ifdef __BIG_ENDIAN__
uh->pktsize = uwsgi_swap16((uint16_t) b->used - 4);
#else
uh->pktsize = b->used - 4;
#endif
uh->modifier2 = (uint8_t) 0;
log_error_write(srv, __FILE__, __LINE__, "sd", "uwsgi_header ", b->used - 4);
b->used++; /* fix size */
hctx->wb->bytes_in += b->used -1 ;
hctx->wb->bytes_in += b->used -1;
/* body */
if (con->request.content_length) {
@@ -520,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;
@@ -621,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) {
@@ -681,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) {
@@ -735,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;
}
@@ -774,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;
@@ -908,7 +964,6 @@ static int mod_uwsgi_patch_connection(server *srv, connection *con, plugin_data
PATCH(extensions);
PATCH(debug);
PATCH(balance);
/* skip the first, the global context */
for (i = 1; i < srv->config_context->used; i++) {
@@ -926,8 +981,6 @@ static int mod_uwsgi_patch_connection(server *srv, connection *con, plugin_data
PATCH(extensions);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("uwsgi.debug"))) {
PATCH(debug);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("uwsgi.balance"))) {
PATCH(balance);
}
}
}
@@ -953,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) {
@@ -1000,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",
@@ -1008,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;
}
}
@@ -1041,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
@@ -1097,7 +1150,6 @@ static handler_t uwsgi_handle_fdevent(void *s, void *ctx, int revents) {
static handler_t mod_uwsgi_check_extension(server *srv, connection *con, void *p_d) {
plugin_data *p = p_d;
size_t s_len;
unsigned long last_max = ULONG_MAX;
int max_usage = INT_MAX;
int ndx = -1;
size_t k;
@@ -1143,13 +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) {
if (s_len > ct_len + 1) {
char *pi_offset;
if (0 != (pi_offset = strchr(fn->ptr + ct_len + 1, '/'))) {
path_info_offset = pi_offset - fn->ptr;
}
}
path_info_offset = ct_len;
extension = ext;
break;
}
@@ -1274,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:",
+199
View File
@@ -0,0 +1,199 @@
#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
static int lock_counter = 0;
void uwsgi_lock_init(void *lock) {
char filename[17];
if (snprintf(filename, 17, ".uwsgiflock%d", lock_counter) < 0) {
uwsgi_log("unable to create lock %d\n", lock_counter);
}
int fd = open(filename, O_CREAT|O_RDWR|O_TRUNC);
if (fd < 0) {
uwsgi_error_open(filename);
exit(1);
}
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;
}
+211
View File
@@ -0,0 +1,211 @@
#define _NO_UWSGI_RB
#include "uwsgi.h"
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
#include <kvm.h>
#include <sys/user.h>
#elif defined(__sun__)
/* Terrible Hack !!! */
#ifndef _LP64
#undef _FILE_OFFSET_BITS
#endif
#include <procfs.h>
#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;
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.apps[wsgi_req->app_id];
if (wi->requests > 0) {
app_req = wi->requests;
}
}
#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
time_request = ctime((const time_t *) &wsgi_req->start_of_request.tv_sec);
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
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
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++;
}
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() {
#ifdef UNBIT
uwsgi.workers[uwsgi.mywid].vsz_size = syscall(356);
#elif defined(__linux__)
FILE *procfile;
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", (unsigned long long *) &uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long *) &uwsgi.workers[uwsgi.mywid].rss_size);
if (i != 2) {
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;
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;
}
close(procfd);
}
#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);
if (task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t) & t_info, &t_size) == KERN_SUCCESS) {
uwsgi.workers[uwsgi.mywid].rss_size = t_info.resident_size;
uwsgi.workers[uwsgi.mywid].vsz_size = t_info.virtual_size;
}
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
kvm_t *kv;
int cnt;
kv = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
if (kv) {
#if defined(__FreeBSD__) || defined(__DragonFly__)
struct kinfo_proc *kproc;
kproc = kvm_getprocs(kv, KERN_PROC_PID, uwsgi.mypid, &cnt);
if (kproc && cnt > 0) {
uwsgi.workers[uwsgi.mywid].vsz_size = kproc->ki_size;
uwsgi.workers[uwsgi.mywid].rss_size = kproc->ki_rssize * uwsgi.page_size;
}
#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
}
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

+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;
}
+1102
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>
+13
View File
@@ -0,0 +1,13 @@
[uwsgi]
socket = :3033
socket = :3034
vacuum = true
socket = pippo1.sock
socket = pippo2.sock
socket = 127.0.0.1:1717
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}
+7
View File
@@ -0,0 +1,7 @@
import uwsgi
import struct
import sys
print uwsgi.send_uwsgi_message(sys.argv[1], int(sys.argv[2]), 10, int(sys.argv[3]), struct.pack("i", int(sys.argv[4])))
+1305 -1226
View File
File diff suppressed because it is too large Load Diff
+64
View File
@@ -0,0 +1,64 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
void embed_plugins() {
#ifdef UWSGI_EMBED_PLUGIN_PSGI
if (uwsgi.plugin_arg_psgi)
uwsgi_load_plugin(5, "psgi_plugin.so", uwsgi.plugin_arg_psgi, 0);
#endif
#ifdef UWSGI_EMBED_PLUGIN_LUA
if (uwsgi.plugin_arg_lua)
uwsgi_load_plugin(6, "lua_plugin.so", uwsgi.plugin_arg_lua, 0);
#endif
#ifdef UWSGI_EMBED_PLUGIN_RACK
if (uwsgi.plugin_arg_rack)
uwsgi_load_plugin(7, "rack_plugin.so", uwsgi.plugin_arg_rack, 0);
#endif
}
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;
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;
return -1;
}
+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']
+454
View File
@@ -0,0 +1,454 @@
#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 = {
.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;
};

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