Compare commits

..
288 Commits
Author SHA1 Message Date
Unbit ccf298a148 updated gemspec 2013-04-23 14:29:45 +02:00
Unbit 914b600af4 prepare for 1.9.8 2013-04-23 14:27:47 +02:00
Unbit 4944994667 fixed #244 2013-04-23 14:27:08 +02:00
Unbit 3a487578a5 remove annoying logline in async mode 2013-04-23 10:10:13 +02:00
Unbit 39eeccb16a refactored async runqueue management 2013-04-23 10:02:36 +02:00
Roberta Giordano 32acd3b9d1 added the flush instruction 2013-04-23 07:07:53 +02:00
Roberta Giordano c57baae477 mime route var has to take variables 2013-04-23 06:46:47 +02:00
Unbit 4a6ed633b9 added hex and base64 routing vars 2013-04-22 16:36:46 +02:00
Unbit 2ab1845547 prepare gemspec for 1.9.7 2013-04-22 15:36:13 +02:00
Unbit f4d2e1f20c added UWSGI_EMBED_PLUGINS 2013-04-22 12:37:31 +02:00
Unbit 81dca1f690 better lock-engine auto-detection 2013-04-22 12:23:59 +02:00
Unbit 2b331fd68f fixed ipcsem removal on reload 2013-04-22 12:16:39 +02:00
Unbit cc77e4dba7 ported gridfs to the new uwsgi_get_app_id function 2013-04-22 10:33:52 +02:00
Unbit 620a13a308 added toxslt transformation 2013-04-22 10:08:56 +02:00
Unbit 42d4ba09d7 refactored uwsgi_get_app_id 2013-04-22 09:43:20 +02:00
Unbit ca071fa52f removed cherokee nginx and lighttpd directories 2013-04-22 08:07:26 +02:00
Unbit d38e5dec7b added uwsgi::register_rpc to perl 2013-04-22 08:05:20 +02:00
Unbit e5db38f7c0 kqueue timer for OpenBSD, NetBSD and DragonFlyBSD 2013-04-22 09:07:19 +02:00
Unbit 68a29730c0 transformation_gzip and transformation_tofile are part of the default build profile 2013-04-22 06:57:29 +02:00
Unbit 5c33c4d341 fixed fd leak in sendfile on error 2013-04-22 06:25:50 +02:00
Unbit a1d6270089 another static gzip refactoring 2013-04-21 20:48:08 +02:00
unbit 1968175b00 Merge pull request #240 from toofishes/static-gz-length
Fix Content-Length header when serving gzipped content
2013-04-21 11:38:18 -07:00
Dan McGee cf1e2aeeba Fix Content-Length header when serving gzipped content
The refactor in a56003d8 to support the Range header broke compliance
with the HTTP spec. When we find a gzipped resource to serve up, ensure
we use the correct Content-Length of the compressed file, not the
original one.
2013-04-21 13:16:33 -05:00
Unbit 199b0b9f57 resources allocated by transformations are correctly freed 2013-04-21 10:22:33 +02:00
Unbit 87a0daa465 ported gzip and toupper to the new transformation api 2013-04-21 10:17:37 +02:00
Unbit c2af90b58f cachestore response is buffered 2013-04-21 10:09:02 +02:00
Unbit 62f01453af refactored cachestore to use transformation api 2013-04-21 10:07:48 +02:00
Unbit 375d6ee331 allows non-request plugin to register rpc functions 2013-04-21 09:43:45 +02:00
Unbit 222ca2915b symcall has been improved and added to the dfault build profile 2013-04-20 19:22:50 +02:00
Unbit 5ca848f9fe more robust subscription propagation using non blocking sockets 2013-04-20 15:17:43 +02:00
Unbit 68d878ff6b added arbiters to the Legion subsystem 2013-04-20 14:20:32 +02:00
Unbit 782a7b418a added mime route var 2013-04-20 13:56:10 +02:00
Unbit 724d7854ad allows transformation to rewrite headers 2013-04-20 13:51:48 +02:00
Unbit f8e64d17e8 added safe-fd concept and --alarm-fd 2013-04-20 13:24:36 +02:00
Unbit 3b40799000 more robust error checking for cgroups and support for writing proc files on the fly 2013-04-20 10:49:42 +02:00
Roberta Giordano 709964ca92 raise an exception with python3 if the headers are not encodable in latin1 2013-04-20 08:08:53 +02:00
Unbit d2cdedc610 maintain headers sent as the last resort even in buffered mode 2013-04-18 22:09:05 +02:00
Unbit b7d0730343 fixed another typo 2013-04-18 18:06:07 +02:00
Unbit 30b4ea7d49 added transformation_gzip 2013-04-18 18:05:01 +02:00
Unbit 546dadbd06 fixed some typo 2013-04-18 17:59:24 +02:00
Unbit 76edf902de added trasnformations 2013-04-18 17:56:13 +02:00
Unbit 068024134c added --load-file-in-cache-gzip 2013-04-17 16:08:27 +02:00
Unbit 538ab57b6e extend magic cache api to export the expires value (if available) 2013-04-16 18:56:25 +02:00
Unbit fd6d9148f3 filter more headers in proxy mode 2013-04-16 18:00:30 +02:00
Unbit f033f59755 fixed gzip caching 2013-04-16 17:51:50 +02:00
Unbit 7168c6dd69 improved caching 2013-04-16 17:46:36 +02:00
Unbit f121d41c2f added proxyhttp and proxyuwsgi 2013-04-16 17:11:32 +02:00
Unbit e56e774eac Merge branch 'master' of github.com:unbit/uwsgi 2013-04-16 10:17:29 +02:00
Unbit 6d9b0918a3 do not skip atexit hooks on end_me when run by the master 2013-04-16 10:17:11 +02:00
unbit d445418611 Merge pull request #229 from prymitive/cb_in_base
add cheaper_busyness plugin to default build profile
2013-04-16 01:12:52 -07:00
Unbit 6d15a51c9a added --skip-atexit 2013-04-16 10:12:22 +02:00
unbit 42a615efdd Merge pull request #231 from prymitive/legion_lock
add missing locks to legion_cache_fetch plugin
2013-04-15 10:32:01 -07:00
Łukasz Mierzwa 54cd1f79a6 add missing locks to legion_cache_fetch plugin 2013-04-15 19:15:54 +02:00
Unbit 8ed8f46374 fixed some minor-bug dected by cppcheck 2013-04-15 13:45:46 +02:00
Unbit dd3a2996a4 fixed leak in cache gzip 2013-04-15 13:22:26 +02:00
Unbit bf1f90a96a added the ability to store cache items in gzip 2013-04-15 12:36:27 +02:00
Unbit 2d6200231a added content_encoding to routing cache 2013-04-15 11:28:54 +02:00
Unbit 032cd23304 added --legion-mcast shortcut 2013-04-14 18:12:57 +02:00
Łukasz Mierzwa de4c0a9e1c add cheaper_busyness plugin to default build profile 2013-04-14 12:28:49 +02:00
Unbit e33f8e8920 compile the remote spooler plugin by default 2013-04-14 09:39:46 +02:00
Unbit 22615c7921 correctly support default cache in ssl session scaling 2013-04-14 08:23:48 +02:00
Unbit 9d8809c580 added the curl_cron plugin 2013-04-13 10:04:21 +02:00
Unbit 96b92c98ff refactored cron to allows better plugins integration 2013-04-13 09:22:22 +02:00
unbit 07939acecd Merge pull request #228 from prymitive/cache_last_modified
store cache last modification time if enabled, fixes #224
2013-04-13 00:08:10 -07:00
Łukasz Mierzwa 30abcb2563 store cache last modification time if enabled, fixes #224 2013-04-12 22:11:25 +02:00
Unbit 35ce8f2b8d do not spawn the excpetion thread handler if no exception handler has been loaded 2013-04-12 08:12:15 +02:00
Unbit d6453eab38 improved cache usage in corerouters 2013-04-11 20:25:18 +02:00
Unbit e0964d07ea ported router_http improvements to router_uwsgi 2013-04-11 17:59:49 +02:00
Unbit fc359f1956 better to set status to 202 for offloaded requests 2013-04-11 17:39:20 +02:00
Unbit 322261d65d Merge branch 'master' of github.com:unbit/uwsgi 2013-04-11 17:26:42 +02:00
Unbit bd1163c439 fixed websocket proxy 2013-04-11 17:24:44 +02:00
unbit e203a8c706 Merge pull request #226 from prymitive/legion_log_fixes
remove unnecessary new lines in legion logs
2013-04-11 05:54:16 -07:00
unbit 6a1ba2af74 Merge pull request #225 from prymitive/cron_interval_fix
execute cron tasks with 60 second resolution, instead of 61 seconds
2013-04-11 05:37:00 -07:00
Łukasz Mierzwa 22569e64df remove unnecessary new lines in legion logs 2013-04-11 14:33:38 +02:00
Łukasz Mierzwa dcafe41cde execute cron tasks with 60 second resolution, instead of 61 seconds 2013-04-11 14:09:49 +02:00
Unbit dd2adc08a3 fixed teajs support 2013-04-11 12:25:06 +02:00
Unbit d7534d2673 improve post_buffering management in http internal router 2013-04-11 12:20:32 +02:00
Unbit 0a59920025 honour http protocol in http internal router 2013-04-11 11:47:14 +02:00
Unbit 77602a8de4 improved websockets detection 2013-04-11 11:30:15 +02:00
Unbit 65b3fde97c added --legion-cron 2013-04-11 09:37:22 +02:00
unbit b690148452 Merge pull request #223 from prymitive/lcf_fixes
free values on old sync node list
2013-04-10 22:52:55 -07:00
Łukasz Mierzwa 4c7bc9ada6 free list value before we free list itself 2013-04-10 22:12:06 +02:00
Unbit 432651489f let's start with 1.9.7 2013-04-10 19:04:12 +02:00
unbit 82aa232a37 Merge pull request #221 from prymitive/legion_cache_plugin2
plugin for fetching cache dump from any node after joining legion
2013-04-10 09:32:41 -07:00
Unbit 19b13bf7a7 fixed offloading and more metric analysis 2013-04-10 18:21:28 +02:00
Łukasz Mierzwa f7e25d807d Merge remote branch 'upstream/master' into legion_cache_plugin2 2013-04-10 15:57:04 +02:00
unbit cf05316b95 Merge pull request #210 from prymitive/cron_refactoring
move crontab entry parsing to separate function
2013-04-10 06:40:30 -07:00
Łukasz Mierzwa 001c4386b5 move crontab entry parsing to separate function 2013-04-10 15:37:10 +02:00
Łukasz Mierzwa 572527f8cb plugin for fetching cache dump from any node after joining legion 2013-04-10 13:28:03 +02:00
Unbit b4252beda6 updated gemspec 2013-04-09 19:05:26 +02:00
Unbit d82ee16e0c completed first step of teajs integration, improved environ copy 2013-04-09 18:54:08 +02:00
unbit e4d65c07ce added support for gcc 4.8 2013-04-09 15:48:58 +02:00
Unbit 86fcb78cc3 fix for broken linkers 2013-04-09 14:51:47 +02:00
unbit 5beb422d75 Merge pull request #219 from prymitive/legion_cache_plugin
cache refactoring for better plugin friendliness
2013-04-09 05:48:49 -07:00
Łukasz Mierzwa 53679879ca cache refactoring for better plugin friendliness 2013-04-09 14:15:33 +02:00
Unbit a8ad766182 fixed matheval route var, added time route var 2013-04-09 11:09:15 +02:00
Unbit cbb2d30f79 more analysis for the metric subsystem 2013-04-09 06:38:34 +02:00
Unbit c5e00bcec6 preparing for uWSGI 1.9.6 2013-04-09 06:13:51 +02:00
Unbit 51535d374d reindented uwsgi.h 2013-04-09 06:13:28 +02:00
Unbit 1e057e6c35 the ldap support is now a plugin 2013-04-09 05:55:18 +02:00
Unbit b23e8ab862 added --socket-sndbuf and --socket-rcvbuf 2013-04-08 20:41:54 +02:00
Unbit 0f7f13dfb2 prepare for TeaJS integration 2013-04-08 19:50:01 +02:00
Unbit aa19ccda1d removed the probe subsystem 2013-04-08 17:05:12 +02:00
unbit cd0129e780 Merge pull request #218 from prymitive/legion_hooks
more legion hooks
2013-04-08 06:53:55 -07:00
Łukasz Mierzwa 506c9023e6 more legion hooks 2013-04-08 15:48:16 +02:00
Unbit d47c25ea4c added --lua-shell 2013-04-08 14:16:36 +02:00
Unbit 010651073c added rbshell 2013-04-08 13:49:23 +02:00
Unbit 76364e3799 added 'alarm' routing action 2013-04-08 11:10:18 +02:00
Unbit f9fd0a0203 added uwsgi route var 2013-04-08 10:34:45 +02:00
Unbit 8dfbde5d16 added --for-times 2013-04-08 10:20:22 +02:00
Unbit 888991f8c1 core/metrics.c 2013-04-08 09:39:57 +02:00
Unbit ece03922d6 added gridfs authentication 2013-04-06 15:09:01 +02:00
Unbit 47bb827e6e added 'lord' routing condition 2013-04-06 13:46:21 +02:00
Unbit a56003d847 added support for range header 2013-04-06 12:45:03 +02:00
Unbit 61022c398c added rpcraw 2013-04-06 08:42:55 +02:00
Unbit 00bd8cc525 improved pyshell 2013-04-06 07:44:12 +02:00
Unbit cf6a232aef added check for seek and tell in wsgi 2013-04-06 07:33:25 +02:00
Unbit 59d1a45ef0 added math route var 2013-04-05 19:26:33 +02:00
Unbit 0b5f9fcb48 added math[] route var 2013-04-05 18:39:01 +02:00
Unbit f713ffd6a1 improved mongodb dumb plugin 2013-04-05 18:17:28 +02:00
Unbit 22ba9d81d4 more generic mongodb plugin 2013-04-05 17:51:41 +02:00
Unbit 309bc98d7f added simple numeric checks for routing conditions 2013-04-05 17:48:20 +02:00
unbit 9b8646a583 Merge pull request #213 from prymitive/carbon_avg_policy
adds ability to control what values (if any) for avg_rt will be sent if ...
2013-04-05 02:18:19 -07:00
Unbit 48d1b87ab8 completed sqlite3 plugin 2013-04-05 10:37:18 +02:00
Unbit c5f849d846 added sqlite3 plugin 2013-04-05 10:35:30 +02:00
Unbit 31fbb6e4f5 prepare for moving sqlite to a dedicated plugin 2013-04-05 10:29:49 +02:00
Unbit 4d9a88e999 added setfile routing instruction and improved uwsgi_get_var 2013-04-05 07:47:32 +02:00
Unbit 252e8484a8 added chdir,setapp and sethome routing actions 2013-04-04 11:19:31 +02:00
Unbit 1b89203932 prepare for language independent home concept 2013-04-04 11:03:26 +02:00
Unbit 2263c6a618 prepare for uWSGI 1.9.5 release 2013-04-04 09:08:10 +02:00
Łukasz Mierzwa 673cb3ee21 adds ability to control what values (if any) for avg_rt will be sent if no requests were done, fixes #212 2013-04-04 00:55:02 +02:00
Unbit b4ecd504e3 prepare for 1.9.5 2013-04-03 19:19:23 +02:00
Unbit f226f29428 fix psgi post buffering 2013-04-03 18:20:54 +02:00
Unbit b87a284390 added 404/403 management for cgi routing 2013-04-03 18:09:05 +02:00
Unbit f63dcd0d9c fixed escaping in kvlist parse 2013-04-03 17:57:49 +02:00
Unbit 7f5563d581 added cgi router 2013-04-03 15:18:46 +02:00
Unbit d8a61a920e allows building a monolithic gridfs binary 2013-04-03 12:41:07 +02:00
Unbit 5a4900da8e added gridfs build profile 2013-04-03 12:39:00 +02:00
Unbit 677c30057a added routing support for gridfs 2013-04-03 12:24:21 +02:00
Unbit 26113e091b added the gridfs plugin 2013-04-03 11:54:54 +02:00
Unbit 1b5e98f593 more JSGI request vars 2013-04-02 18:22:39 +02:00
Unbit 0aa5201947 first implementation of a JSGI request 2013-04-02 17:30:58 +02:00
Unbit e3951baa3f completed JSGI response 2013-04-02 16:55:01 +02:00
Unbit 9f9dbbab9e preliminary support for JSGI 3.0 2013-04-02 12:26:55 +02:00
Unbit d546bbadbd added commonjs 'require' implementation to v8 2013-04-02 10:57:52 +02:00
Unbit 2b7f25054f added mule support for v8 2013-04-02 10:00:10 +02:00
Unbit bb3f6bcf7e more solid multithreading support for v8 2013-04-01 21:36:07 +02:00
Unbit 41da7175d1 working on v8 multithreading 2013-04-01 20:19:59 +02:00
Unbit 446763b58a added --honour-stdin 2013-04-01 10:07:33 +02:00
Unbit 3e9337a0fc added --daemons-honour-stdin 2013-04-01 09:30:19 +02:00
Unbit 028806165b force the emperor to honour --max-fd 2013-04-01 09:14:11 +02:00
unbit e4be42edbb Merge pull request #208 from xrmx/coverity11
More issues reported by Coverity
2013-04-01 00:07:29 -07:00
Unbit 230fa1f3bb fixed multiple interpreters support 2013-04-01 09:00:24 +02:00
unbit d74653bbad Merge pull request #209 from xrmx/coverity12
plugins/cgi: fix memory leak in uwsgi_cgi_request
2013-03-31 23:30:15 -07:00
Riccardo Magliocchetti 38049b0897 plugins/cgi: fix memory leak in uwsgi_cgi_request
Reported by Coverity as CID #990186.
2013-03-31 20:12:12 +02:00
Riccardo Magliocchetti b4af646929 core/emperor: fix memory leak in uwsgi_emperor_vassal_start
Reported by Coverity as CID #995786.
2013-03-31 19:51:25 +02:00
Riccardo Magliocchetti b21ec73a52 plugins/carbon: fix memory leak in carbon_post_init
Reported by Coverity as CID #995791
2013-03-31 19:45:24 +02:00
Riccardo Magliocchetti c595844f0e plugins/router_cache: fix memory leak in uwsgi_router_cache_store
Reported by Coverity as CID #995792.
2013-03-31 19:38:58 +02:00
Unbit fe8ee7c7b3 uWSGI 1.9.4 2013-03-30 16:29:51 +01:00
Unbit cd382c6bc0 added rpcblob/rpcnext 2013-03-30 16:06:47 +01:00
Unbit e68296c293 a bit of cosmetic for uwsgi.h 2013-03-30 09:28:06 +01:00
Unbit cc189feae5 added uwsgi_register_signal to v8 2013-03-30 09:25:50 +01:00
unbit 18e19027a1 Merge pull request #207 from prymitive/legion_api
refactored legion opt functions to be more plugin friendly
2013-03-30 00:58:46 -07:00
Łukasz Mierzwa 2d2e0e4757 refactored legion opt functions to be more plugin friendly 2013-03-29 23:33:33 +01:00
Unbit a9f50d79f9 start 1.9.4 2013-03-29 21:24:56 +01:00
Unbit 0ccd31bee0 fixed reloading when in Go mode 2013-03-29 21:24:41 +01:00
Unbit 3ea82b2bcd do not differentiate reload when uWSGI is build as shared library 2013-03-29 21:21:46 +01:00
Unbit 6dad7b3ced ported the cplusplus plugin to the new api 2013-03-29 19:43:03 +01:00
Unbit f96ebd2b07 Merge branch 'master' of github.com:unbit/uwsgi 2013-03-29 19:37:53 +01:00
Unbit b8d0e7a3ac beta quality v8 plugin 2013-03-29 19:37:33 +01:00
unbit 14cca3d497 Merge pull request #204 from prymitive/legion_join_hook
legion join hook
2013-03-29 06:02:42 -07:00
Łukasz Mierzwa c343ca0cc3 legion join hook 2013-03-29 14:01:02 +01:00
Unbit 527d371bda fixed multiple mules event handling 2013-03-29 13:34:48 +01:00
Unbit b87a800a9a avoid resetting uwsgi.mywid in the master 2013-03-29 13:24:33 +01:00
Unbit e406993ed1 fixed typo 2013-03-29 12:51:52 +01:00
Unbit eeff935fc9 fixed signal handling in non-workers 2013-03-29 12:50:56 +01:00
Unbit 0791394f1a official support for SmartOS 2013-03-29 08:12:58 +00:00
unbit 082a407b06 Merge pull request #201 from prymitive/cache_restore_items_count
update cache items count after restore
2013-03-28 15:23:22 -07:00
Łukasz Mierzwa 8a89b49df1 update cache items count after restore 2013-03-28 23:20:17 +01:00
unbit 2314b9cbab Merge pull request #200 from jbert/master
Fix segfault in psgi plugin
2013-03-28 15:02:26 -07:00
John Berthels d0cca85c83 fix segfault in psgi handler after taking early-exit error path in coroae_accept_request 2013-03-28 17:29:00 +00:00
unbit 6a7a5cbcba Merge pull request #199 from prymitive/cache_stats_missin_list_close
missing list close in cache stats
2013-03-28 09:28:02 -07:00
Łukasz Mierzwa ecccc82cc8 missing list close 2013-03-28 16:56:31 +01:00
Unbit 02693489fe fixed php headers generation 2013-03-28 12:13:23 +01:00
Unbit 0f5dba5828 apache 2.4 support in mod_proxy_uwsgi 2013-03-28 11:19:13 +01:00
Unbit e528d4c4b7 implemented --emperor-tyrant-nofollow 2013-03-28 10:18:01 +01:00
Unbit 52a3af6acf prepare for uWSGI 1.9.3 2013-03-28 10:05:24 +01:00
Unbit dcefea9958 added rpcret routing action 2013-03-28 10:03:33 +01:00
Unbit 59121ff834 added --lua-load, fixed lua rpc memory leak 2013-03-28 09:21:47 +01:00
Unbit 7f5bb6d472 allows usage of configurators in the emperor 2013-03-28 09:07:15 +01:00
Unbit 639c1a508c support for lua ordered arrays in configurations 2013-03-28 09:00:10 +01:00
Unbit 417a26fc64 added config.lua example 2013-03-28 08:02:32 +01:00
Unbit 210ccd0063 allows configuration via lua 2013-03-28 08:02:07 +01:00
unbit 1bf0162d38 Merge pull request #196 from ryankask/jvm-plugin-import
Fix imports for the JVM plugin
2013-03-27 02:53:03 -07:00
Ryan Kaskel e93027fd7e Fix imports for JVM plugin. 2013-03-27 09:48:14 +00:00
Unbit 807060706f prepare for 1.9.2 2013-03-26 20:05:33 +01:00
Unbit a317f88d3c added the cache command to the ssi plugin 2013-03-26 20:03:37 +01:00
Unbit e17a7f0701 fixed a typo 2013-03-26 19:53:32 +01:00
Unbit db325eb9fe fixed readline() + post_buffering 2013-03-26 17:54:42 +01:00
Unbit b41a4c8c3b fixed python3 headers management 2013-03-26 16:45:57 +01:00
Unbit 73b4d11d18 added ssi router 2013-03-26 15:38:45 +01:00
Unbit 8162b87287 beta quality ssi plugin 2013-03-26 15:19:23 +01:00
Unbit 70e9e4f3ee added printenv 2013-03-26 12:24:17 +01:00
Unbit e61ae376b3 other improvements in the ssi plugin 2013-03-26 11:48:51 +01:00
Unbit 2d57b0e926 added preliminary ssi support 2013-03-26 11:33:00 +01:00
Unbit ae683af07a completed the geoip plugin [2] 2013-03-26 07:11:27 +01:00
Unbit 3c4f6a9171 completed the geoip plugin 2013-03-26 07:05:02 +01:00
Unbit 39986e546c fixed GeoIP plugin 2013-03-26 06:47:18 +01:00
Unbit 2e81a80f7b added preliminary geoip plugin 2013-03-25 19:11:20 +01:00
Unbit fcb3aa38c8 allows freeing route vars 2013-03-25 18:15:29 +01:00
Unbit 00a38d8ec5 fixed routing vars management 2013-03-25 18:10:41 +01:00
Unbit 07a0ab4227 pluggable routing vars 2013-03-25 18:05:57 +01:00
Unbit d4a9a2c543 fixed exceptions in the fiber plugin 2013-03-25 17:46:29 +01:00
Unbit 2b523fc60d added query string management functions 2013-03-25 10:21:20 +01:00
Unbit 0c26928236 added cookie management and --route-run 2013-03-25 09:56:53 +01:00
Unbit 8401e56a22 added 'empty' internal routing condition 2013-03-25 09:04:30 +01:00
Unbit 5109f9ae0b back to libxml2 default 2013-03-25 08:47:22 +01:00
Unbit c9bc06669a .ini file can backreference themselves 2013-03-25 08:47:00 +01:00
unbit a83fb2672c Merge pull request #189 from xtfxme/enhance/189-dashful-endif-endfor
Routing table appear to go nuts when used within a FOR loop
2013-03-24 23:18:50 -07:00
C Anthony Risinger 8f9ecb44d9 [#189] endfor/endif => end-for/end-if ...i know i'm not alone 2013-03-24 15:45:04 -05:00
Unbit bfcc09a8de prepare for cookie management in internal routing 2013-03-24 21:05:21 +01:00
Unbit f8a8c997db removed cache type in routing instruction 2013-03-24 20:30:56 +01:00
Unbit 132b996f30 added cachestore routing instruction 2013-03-24 19:43:41 +01:00
Unbit 12f970cdfb prepare for routing-governed caching 2013-03-24 19:24:13 +01:00
Unbit 9afa963225 prepare for gem 1.9.1 2013-03-24 11:39:44 +01:00
Unbit ed368d0d51 fixed signal copy on write 2013-03-24 10:30:01 +01:00
Unbit 21f21d34ba fixed legion scrolls api 2013-03-24 09:52:16 +01:00
Unbit f37823c809 completed --emperor-on-demand-dir 2013-03-23 10:34:36 +01:00
Unbit 6eaefcff5e added build profile for ubuntu ppa 2013-03-23 06:15:55 +01:00
Unbit 79235c1cc3 another memory report fix for Unbit 2013-03-23 04:41:58 +01:00
Unbit 29135f014b Unbit fixes 2013-03-23 04:11:33 +01:00
Unbit 13c998fb8d added uwsgi_main.c 2013-03-23 03:56:56 +01:00
Unbit 71bfd0d636 prepare for uWSGI 1.9.1 2013-03-23 03:52:19 +01:00
Unbit 51e99e0f5a removed UWSGI_INI 2013-03-23 03:15:33 +01:00
Unbit 66e7beefc4 fixed rack exceptions management 2013-03-22 19:53:47 +01:00
Unbit f2b10c35b7 fixed build without pcre 2013-03-22 11:15:13 +01:00
Unbit e951eba96c improved emperor on demand mode 2013-03-22 14:56:49 +01:00
Unbit 9fe18da7a3 added startswith endswith and regexp/re routing instructions 2013-03-22 10:14:34 +01:00
Unbit a14fdead14 added rpc router instruction 2013-03-22 09:26:11 +01:00
Unbit 9a671a4991 added %V magic var (contains UWSGI_VERSION) 2013-03-21 17:18:41 +01:00
Unbit 8f5e7b124a added --emperor-on-demand-exec 2013-03-21 16:55:23 +01:00
Unbit 5f7464d015 implemented --emperor-on-demand-ext 2013-03-21 16:42:24 +01:00
Unbit 238dd6c1d0 added a commodity mongodb plugin for system without mongoclient shared library 2013-03-21 15:18:09 +01:00
Roberta Giordano 82e4e54edc removed some unbit useless definition 2013-03-21 07:59:45 +01:00
Unbit 9946cbb9da added 'equal' routing func 2013-03-21 06:54:36 +01:00
Unbit 2474adb23a completed routing cache instruction 2013-03-21 06:31:26 +01:00
Unbit f40757bb67 free carbon_address memory 2013-03-21 06:19:31 +01:00
unbit bc29479930 Merge pull request #188 from prymitive/carbon_resolve_hostnames
allow connecting to carbon server using hostname resolved on every cycle...
2013-03-20 22:04:50 -07:00
Łukasz Mierzwa 4ec78edaa3 allow connecting to carbon server using hostname resolved on every cycle, fixes #186 2013-03-20 21:47:56 +01:00
Unbit aa0271158d allows build profiles to be stored on http/https/ftp 2013-03-20 19:44:46 +01:00
Unbit c0aa5bfe17 added the crypto logger 2013-03-20 16:22:40 +01:00
Unbit 3f8e6a8cc8 completed xslt plugin 2013-03-19 17:53:12 +01:00
Unbit ef0316fc2e Merge branch 'master' of github.com:unbit/uwsgi 2013-03-19 15:18:33 +01:00
Unbit 7274efab15 added xslt plugin 2013-03-19 15:18:03 +01:00
Unbit e44b62b6b2 on demand vassals 2013-03-18 15:42:34 +01:00
Unbit 31c041d435 added --exec-post-app 2013-03-18 13:32:09 +01:00
Unbit 35f47371ed first part of uwsgi_legion_scrolls() function api 2013-03-18 13:22:10 +01:00
unbit c5412e1620 Merge pull request #185 from guokr/master
Supporting JVM/Ring installing in Virtualenv
2013-03-18 03:09:03 -07:00
Mingli a9b4c52811 supporting virtualenv 2013-03-18 17:53:04 +08:00
Roberto De Ioris 5ce40b6ac8 fixed --req-logger after reload 2013-03-18 09:19:25 +01:00
Unbit b93dcbf46f removed download_url from setup.py 2013-03-17 08:10:12 +01:00
Unbit 8051a2bc98 prepare for 1.9 release 2013-03-17 07:15:24 +01:00
Unbit 78d8b221fc added --gevent-monkey-patch 2013-03-17 07:14:54 +01:00
Unbit d51cada284 second (and last i hope) part of mongrel2 support refactoring 2013-03-16 18:24:25 +01:00
Unbit 389eef9e88 first part of mongrel2 support refactoring 2013-03-16 18:02:11 +01:00
Unbit 270fb0c50d avoid routing loop 2013-03-16 16:48:26 +01:00
Unbit e7e9dfee88 fixed DragonFlyBSD support 2013-03-16 15:45:49 +01:00
Unbit 3bafae276d improved binary detection path on cygwin 2013-03-16 12:33:00 +01:00
Unbit cfebe2927d fixed lazy mode 2013-03-15 13:47:29 +01:00
Unbit 1d4294a845 added some comment for the statsd plugin 2013-03-15 11:34:19 +01:00
Unbit 12cfdd9864 added stats_pusher_statsd plugin 2013-03-15 11:32:08 +01:00
Unbit add930c517 fixed uuid support in cygwin 2013-03-15 07:31:41 +01:00
Unbit 32972978be added java support for cygwin 2013-03-13 17:50:56 +01:00
Unbit c8bad3550e added proper locking to windows 2013-03-13 15:51:14 +01:00
Unbit ecc55d789d added proper-locking to poll event mode 2013-03-13 15:03:30 +01:00
Unbit 88555e2c20 improved poll() support 2013-03-13 14:33:38 +01:00
Unbit ec2bfcd302 allows building router basicauth on cygwin 2013-03-13 11:14:32 +01:00
Unbit f1f81ed4c4 fixed python3 build 2013-03-13 11:00:05 +01:00
Unbit 87933cca26 another series of cygwin fixes 2013-03-13 10:51:33 +01:00
Unbit 2dcd8624a2 psgi support for windows 2013-03-13 10:12:24 +01:00
Unbit 7fcef76bbe experimental windows/cygwin support 2013-03-13 09:44:32 +01:00
Unbit 2a5c4e938d fixed requets overwrite in PATH_INFO rewrite (fixed typo) 2013-03-12 15:57:44 +01:00
Unbit 274eae27ef fixed requets overwrite in PATH_INFO rewrite 2013-03-12 15:56:30 +01:00
Unbit 207220bc50 fixed #180 2013-03-12 11:45:03 +01:00
Unbit fb8c4439c7 the whole ring test suite passes 2013-03-12 11:15:45 +01:00
Roberto De Ioris 894be9c41e let the /sequence ring test pass 2013-03-12 09:42:13 +01:00
unbit 0a4bff8963 Merge pull request #182 from guokr/master
Ring plugin tests
2013-03-12 00:27:11 -07:00
Mingli d515f3e279 add tests for ring plugin 2013-03-12 14:47:51 +08:00
169 changed files with 10541 additions and 6699 deletions
+4
View File
@@ -1,5 +1,9 @@
*.o
*.py[co]
*.class
*.jar
/uwsgi
/uwsgibuild.*
/t/ring/target
+43
View File
@@ -217,6 +217,45 @@ static int uwsgi_send_body(request_rec *r, proxy_conn_rec *conn)
return OK;
}
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
static request_rec *ap_proxy_make_fake_req(conn_rec *c, request_rec *r)
{
apr_pool_t *pool;
request_rec *rp;
apr_pool_create(&pool, c->pool);
rp = apr_pcalloc(pool, sizeof(*r));
rp->pool = pool;
rp->status = HTTP_OK;
rp->headers_in = apr_table_make(pool, 50);
rp->subprocess_env = apr_table_make(pool, 50);
rp->headers_out = apr_table_make(pool, 12);
rp->err_headers_out = apr_table_make(pool, 5);
rp->notes = apr_table_make(pool, 5);
rp->server = r->server;
rp->log = r->log;
rp->proxyreq = r->proxyreq;
rp->request_time = r->request_time;
rp->connection = c;
rp->output_filters = c->output_filters;
rp->input_filters = c->input_filters;
rp->proto_output_filters = c->output_filters;
rp->proto_input_filters = c->input_filters;
rp->useragent_ip = c->client_ip;
rp->useragent_addr = c->client_addr;
rp->request_config = ap_create_request_config(pool);
proxy_run_create_req(r, rp);
return rp;
}
#endif
static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_conf *conf)
{
@@ -337,7 +376,11 @@ static int uwsgi_handler(request_rec *r, proxy_worker *worker,
}
// ADD PATH_INFO
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
size_t w_len = strlen(worker->s->name);
#else
size_t w_len = strlen(worker->name);
#endif
char *u_path_info = r->filename + 6 + w_len;
int delta = 0;
if (u_path_info[0] != '/') {
-1
View File
@@ -1 +0,0 @@
object file for embedded files will be put here
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi
inherit = base
+1 -8
View File
@@ -1,18 +1,11 @@
[uwsgi]
xml = auto
ini = true
yaml = true
json = auto
sqlite3 = auto
zeromq = auto
snmp = true
ssl = auto
async = true
ldap = auto
pcre = auto
routing = auto
alarm = auto
ipv6 = false
debug = false
unbit = false
xml_implementation = libxml2
@@ -23,7 +16,7 @@ plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter, router_static, sslrouter
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter, router_static, sslrouter, spooler, cheaper_busyness, symcall, transformation_tofile, transformation_gzip
as_shared_library = false
locking = auto
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = gridfs
inherit = base
+32
View File
@@ -0,0 +1,32 @@
[uwsgi]
xml = true
yaml = true
json = true
zeromq = true
ssl = true
pcre = true
routing = true
debug = false
unbit = false
xml_implementation = libxml2
yaml_implementation = libyaml
malloc_implementation = libc
extras =
plugins =
bin_name = /usr/lib/libuwsgi.so
append_version = ubuntu
plugin_dir = /usr/lib/uwsgi
embedded_plugins =
as_shared_library = true
locking = auto
event = auto
timer = auto
filemonitor = auto
blacklist =
whitelist =
embed_files =
embed_config =
+6
View File
@@ -0,0 +1,6 @@
[uwsgi]
main_plugin = python,gevent
inherit = base
plugins = jvm,ring
plugin_dir = .
+12 -6
View File
@@ -1,26 +1,32 @@
[uwsgi]
xml = true
ini = true
yaml = true
json = false
sqlite3 = false
zeromq = false
ldap = true
ssl = true
pcre = true
routing = true
alarm = true
debug = false
unbit = true
xml_implementation = expat
yaml_implementation = auto
malloc_implementation = libc
extras =
plugins =
bin_name = /opt/unbit/bin/uwsgi
bin_name = /opt/unbit/uwsgi19/lib/libuwsgi.so
append_version = unbit
plugin_dir = /opt/unbit/uwsgi_plugins
plugin_dir = /opt/unbit/uwsgi19/plugins
embedded_plugins =
as_shared_library = true
locking = auto
event = auto
timer = auto
filemonitor = auto
blacklist =
whitelist =
embed_files =
embed_config =
-1
View File
@@ -1,6 +1,5 @@
[uwsgi]
inherit = unbit
json = false
embedded_plugins = python
bin_name = ../bin/uwsgi
plugin_dir = ../bin/uwsgi_plugins
-1
View File
@@ -1 +0,0 @@
the uwsgi handler is included in the official Cherokee distribution
+24
View File
@@ -0,0 +1,24 @@
require 'socket'
require 'openssl'
secret = 'ciaociao'
iv = ''
address = '127.0.0.1'
port = 1717
algo = 'bf-cbc'
s = UDPSocket.new
s.bind(address, port)
cipher = OpenSSL::Cipher.new(algo)
cipher.decrypt
cipher.key = secret + ("\0" * (cipher.key_len - secret.length))
cipher.iv = iv + ("0" * (cipher.iv_len - iv.length))
loop do
msg, sender = s.recvfrom(8192)
cipher.reset
begin
puts cipher.update(msg) + cipher.final
rescue
end
end
+139 -10
View File
@@ -11,6 +11,29 @@ void uwsgi_alarm_func_signal(struct uwsgi_alarm_instance *uai, char *msg, size_t
uwsgi_route_signal(uai->data8);
}
// simply log an alarm
void uwsgi_alarm_init_log(struct uwsgi_alarm_instance *uai) {
}
void uwsgi_alarm_func_log(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
if (msg[len-1] != '\n') {
if (uai->arg && strlen(uai->arg) > 0) {
uwsgi_log_alarm("] %s %.*s\n", uai->arg, len, msg);
}
else {
uwsgi_log_alarm("] %.*s\n", len, msg);
}
}
else {
if (uai->arg && strlen(uai->arg) > 0) {
uwsgi_log_alarm("] %s %.*s", uai->arg, len, msg);
}
else {
uwsgi_log_alarm("] %.*s", len, msg);
}
}
}
// run a command on alarm
void uwsgi_alarm_init_cmd(struct uwsgi_alarm_instance *uai) {
uai->data_ptr = uai->arg;
@@ -86,6 +109,7 @@ void uwsgi_register_embedded_alarms() {
uwsgi_register_alarm("signal", uwsgi_alarm_init_signal, uwsgi_alarm_func_signal);
uwsgi_register_alarm("cmd", uwsgi_alarm_init_cmd, uwsgi_alarm_func_cmd);
uwsgi_register_alarm("mule", uwsgi_alarm_init_mule, uwsgi_alarm_func_mule);
uwsgi_register_alarm("log", uwsgi_alarm_init_log, uwsgi_alarm_func_log);
}
static int uwsgi_alarm_add(char *name, char *plugin, char *arg) {
@@ -189,21 +213,54 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
#endif
static void uwsgi_alarm_thread_loop(struct uwsgi_thread *ut) {
// add uwsgi_alarm_fd;
struct uwsgi_alarm_fd *uafd = uwsgi.alarm_fds;
while(uafd) {
event_queue_add_fd_read(ut->queue, uafd->fd);
uafd = uafd->next;
}
char *buf = uwsgi_malloc(uwsgi.alarm_msg_size + sizeof(long));
for (;;) {
int interesting_fd = -1;
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
if (ret > 0) {
ssize_t len = read(ut->pipe[1], buf, uwsgi.alarm_msg_size + sizeof(long));
if (len > (ssize_t)(sizeof(long) + 1)) {
size_t msg_size = len - sizeof(long);
char *msg = buf + sizeof(long);
long ptr = 0;
memcpy(&ptr, buf, sizeof(long));
struct uwsgi_alarm_instance *uai = (struct uwsgi_alarm_instance *) ptr;
if (!uai)
break;
uwsgi_alarm_run(uai, msg, msg_size);
if (interesting_fd == ut->pipe[1]) {
ssize_t len = read(ut->pipe[1], buf, uwsgi.alarm_msg_size + sizeof(long));
if (len > (ssize_t)(sizeof(long) + 1)) {
size_t msg_size = len - sizeof(long);
char *msg = buf + sizeof(long);
long ptr = 0;
memcpy(&ptr, buf, sizeof(long));
struct uwsgi_alarm_instance *uai = (struct uwsgi_alarm_instance *) ptr;
if (!uai)
break;
uwsgi_alarm_run(uai, msg, msg_size);
}
}
// check for alarm_fd
else {
uafd = uwsgi.alarm_fds;
int fd_read = 0;
while(uafd) {
if (interesting_fd == uafd->fd) {
if (fd_read) goto raise;
size_t remains = uafd->buf_len;
while(remains) {
ssize_t len = read(uafd->fd, uafd->buf + (uafd->buf_len-remains), remains);
if (len <= 0) {
uwsgi_error("[uwsgi-alarm-fd]/read()");
uwsgi_log("[uwsgi-alarm-fd] i will stop monitoring fd %d\n", uafd->fd);
event_queue_del_fd(ut->queue, uafd->fd, event_queue_read());
break;
}
remains-=len;
}
fd_read = 1;
raise:
uwsgi_alarm_run(uafd->alarm, uafd->msg, uafd->msg_len);
}
uafd = uafd->next;
}
}
}
}
@@ -243,6 +300,37 @@ void uwsgi_alarms_init() {
if (!uwsgi.alarm_instances) return;
// map alarm file descriptors
usl = uwsgi.alarm_fd_list;
while(usl) {
char *space0 = strchr(usl->value, ' ');
if (!space0) {
uwsgi_log("invalid alarm-fd syntax: %s\n", usl->value);
exit(1);
}
*space0 = 0;
size_t buf_len = 1;
char *space1 = strchr(space0+1, ' ');
if (!space1) {
uwsgi_log("invalid alarm-fd syntax: %s\n", usl->value);
exit(1);
}
char *colon = strchr(space0+1, ':');
if (colon) {
buf_len = strtoul(colon+1, NULL, 10);
*colon = 0;
}
int fd = atoi(space0+1);
uwsgi_add_alarm_fd(fd, usl->value, buf_len, space1+1, strlen(space1+1));
*space0 = ' ';
*space1 = ' ';
if (colon) {
*colon = ':';
}
usl = usl->next;
}
#ifdef UWSGI_PCRE
// then map log-alarm
usl = uwsgi.alarm_logs_list;
@@ -340,3 +428,44 @@ void uwsgi_alarm_trigger(char *alarm_instance_name, char *msg, size_t len) {
uwsgi_error("[uwsgi-alarm-error] uwsgi_alarm_trigger()/writev()");
}
}
struct uwsgi_alarm_fd *uwsgi_add_alarm_fd(int fd, char *alarm, size_t buf_len, char *msg, size_t msg_len) {
struct uwsgi_alarm_fd *old_uafd = NULL, *uafd = uwsgi.alarm_fds;
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(alarm);
if (!uai) {
uwsgi_log("unable to find alarm \"%s\"\n", alarm);
exit(1);
}
if (!buf_len) buf_len = 1;
while(uafd) {
// check if an equal alarm has been added
if (uafd->fd == fd && uafd->alarm == uai) {
return uafd;
}
old_uafd = uafd;
uafd = uafd->next;
}
uafd = uwsgi_calloc(sizeof(struct uwsgi_alarm_fd));
uafd->fd = fd;
uafd->buf = uwsgi_malloc(buf_len);
uafd->buf_len = buf_len;
uafd->msg = msg;
uafd->msg_len = msg_len;
uafd->alarm = uai;
if (!old_uafd) {
uwsgi.alarm_fds = uafd;
}
else {
old_uafd->next = uafd;
}
// avoid the fd to be closed
uwsgi_add_safe_fd(fd);
uwsgi_log("[uwsgi-alarm] added fd %d\n", fd);
return uafd;
}
+11 -16
View File
@@ -52,7 +52,7 @@ static void runqueue_remove(struct uwsgi_async_request *u_request) {
child->prev = parent;
}
if (parent == NULL) {
if (u_request == uwsgi.async_runqueue) {
uwsgi.async_runqueue = child;
}
@@ -67,25 +67,22 @@ static void runqueue_remove(struct uwsgi_async_request *u_request) {
static void runqueue_push(struct wsgi_request *wsgi_req) {
struct uwsgi_async_request *uar;
struct uwsgi_async_request *uar = uwsgi_malloc(sizeof(struct uwsgi_async_request));
uar->prev = NULL;
uar->next = NULL;
uar->wsgi_req = wsgi_req;
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;
uwsgi.async_runqueue = uar;
}
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;
uar->prev = uwsgi.async_runqueue_last;
}
if (uwsgi.async_runqueue_last) {
uwsgi.async_runqueue_last->next = uar;
}
uwsgi.async_runqueue_last = uar;
uwsgi.async_runqueue_cnt++;
}
@@ -393,8 +390,6 @@ void async_loop() {
continue;
}
else if (proto_parser_status < 0) {
if (proto_parser_status == -1)
uwsgi_log("error parsing request\n");
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
close(interesting_fd);
continue;
+26
View File
@@ -328,3 +328,29 @@ int uwsgi_buffer_set_uh(struct uwsgi_buffer *ub, uint8_t modifier1, uint8_t modi
ub->buf[3] = modifier2;
return 0;
}
struct uwsgi_buffer *uwsgi_buffer_from_file(char *filename) {
struct stat st;
int fd = open(filename, O_RDONLY);
if (fd < 0) {
return NULL;
}
if (fstat(fd, &st)) {
close(fd);
return NULL;
}
struct uwsgi_buffer *ub = uwsgi_buffer_new(st.st_size);
ssize_t len = read(fd, ub->buf, st.st_size);
close(fd);
if (len != st.st_size) {
uwsgi_buffer_destroy(ub);
return NULL;
}
ub->pos = len;
return ub;
}
+175 -89
View File
@@ -156,14 +156,14 @@ static void cache_send_udp_command(struct uwsgi_cache *, char *, uint16_t, char
static void cache_sync_hook(char *k, uint16_t kl, char *v, uint16_t vl, void *data) {
struct uwsgi_cache *uc = (struct uwsgi_cache *) data;
if (!uwsgi_strncmp(k, kl, "items", 5)) {
size_t num = uwsgi_str_num(v, vl);
size_t num = uwsgi_str_num(v, vl);
if (num != uc->max_items) {
uwsgi_log("[cache-sync] invalid cache size, expected %llu received %llu\n", (unsigned long long) uc->max_items, (unsigned long long) num);
exit(1);
}
}
if (!uwsgi_strncmp(k, kl, "blocksize", 9)) {
size_t num = uwsgi_str_num(v, vl);
size_t num = uwsgi_str_num(v, vl);
if (num != uc->blocksize) {
uwsgi_log("[cache-sync] invalid cache block size, expected %llu received %llu\n", (unsigned long long) uc->blocksize, (unsigned long long) num);
exit(1);
@@ -200,6 +200,40 @@ static void uwsgi_cache_load_files(struct uwsgi_cache *uc) {
next:
usl = usl->next;
}
#ifdef UWSGI_ZLIB
usl = uwsgi.load_file_in_cache_gzip;
while(usl) {
size_t len = 0;
char *value = NULL;
char *key = usl->value;
uint16_t key_len = usl->len;
char *space = strchr(usl->value, ' ');
if (space) {
// need to skip ?
if (uwsgi_strncmp(uc->name, uc->name_len, usl->value, space-usl->value)) {
goto next2;
}
key = space+1;
key_len = usl->len - ((space-usl->value)+1);
}
value = uwsgi_open_and_read(key, &len, 0, NULL);
if (value) {
struct uwsgi_buffer *gzipped = uwsgi_gzip(value, len);
if (gzipped) {
uwsgi_wlock(uc->lock);
if (!uwsgi_cache_set2(uc, key, key_len, gzipped->buf, gzipped->len, 0, 0)) {
uwsgi_log("[cache-gzip] stored \"%.*s\" in \"%s\"\n", key_len, key, uc->name);
}
uwsgi_rwunlock(uc->lock);
uwsgi_buffer_destroy(gzipped);
}
free(value);
}
next2:
usl = usl->next;
}
#endif
}
@@ -288,21 +322,7 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
(unsigned long long) ((sizeof(struct uwsgi_cache_item)+uc->keysize) * uc->max_items), (unsigned long long) (uc->blocksize * uc->max_items),
(unsigned long long) uc->blocks_bitmap_size);
struct uwsgi_string_list *usl = uc->nodes;
while(usl) {
char *port = strchr(usl->value, ':');
if (!port) {
uwsgi_log("[cache-udp-node] invalid udp address: %s\n", usl->value);
exit(1);
}
// no need to zero the memory, socket_to_in_addr will do that
struct sockaddr_in *sin = uwsgi_malloc(sizeof(struct sockaddr_in));
usl->custom = socket_to_in_addr(usl->value, port, 0, sin);
usl->custom_ptr = sin;
uwsgi_log("added udp node %s for cache \"%s\"\n", usl->value, uc->name);
usl = usl->next;
}
uwsgi_cache_setup_nodes(uc);
uc->udp_node_socket = socket(AF_INET, SOCK_DGRAM, 0);
if (uc->udp_node_socket < 0) {
@@ -311,70 +331,10 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
}
uwsgi_socket_nb(uc->udp_node_socket);
usl = uc->sync_nodes;
while(usl) {
uwsgi_log("[cache-sync] getting cache dump from %s ...\n", usl->value);
int fd = uwsgi_connect(usl->value, 0, 0);
if (fd < 0) {
uwsgi_log("[cache-sync] unable to connect to the cache server\n");
goto next;
}
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size + uc->filesize);
ub->pos = 4;
if (uwsgi_buffer_append(ub, uc->name, uc->name_len)) {
uwsgi_buffer_destroy(ub);
close(fd);
goto next;
}
if (uwsgi_buffer_set_uh(ub, 111, 6)) {
uwsgi_buffer_destroy(ub);
close(fd);
goto next;
}
if (uwsgi_write_nb(fd, ub->buf, ub->pos, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uwsgi_buffer_destroy(ub);
uwsgi_log("[cache-sync] unable to write to the cache server\n");
close(fd);
goto next;
}
size_t rlen = ub->pos;
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uwsgi_buffer_destroy(ub);
uwsgi_log("[cache-sync] unable to read from the cache server\n");
close(fd);
goto next;
}
uwsgi_hooked_parse(ub->buf, ub->pos, cache_sync_hook, uc);
if (uwsgi_read_nb(fd, (char *) uc->items, uc->filesize, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uwsgi_buffer_destroy(ub);
close(fd);
uwsgi_log("[cache-sync] unable to read from the cache server\n");
goto next;
}
// reset the hashtable
memset(uc->hashtable, 0, sizeof(uint64_t) * UMAX16);
// re-fill the hashtable
uwsgi_cache_fix(uc);
uwsgi_buffer_destroy(ub);
close(fd);
break;
next:
if (!usl->next) {
exit(1);
}
uwsgi_log("[cache-sync] trying with the next sync node...\n");
usl = usl->next;
}
uwsgi_cache_sync_from_nodes(uc);
uwsgi_cache_load_files(uc);
}
static uint64_t uwsgi_cache_get_index(struct uwsgi_cache *uc, char *key, uint16_t keylen) {
@@ -456,6 +416,28 @@ char *uwsgi_cache_get2(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint6
return NULL;
}
char *uwsgi_cache_get3(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_t * valsize, uint64_t *expires) {
uint64_t index = uwsgi_cache_get_index(uc, key, keylen);
if (index) {
struct uwsgi_cache_item *uci = cache_item(index);
if (uci->flags & UWSGI_CACHE_FLAG_UNGETTABLE)
return NULL;
*valsize = uci->valsize;
if (expires)
*expires = uci->expires;
uci->hits++;
uc->hits++;
return uc->data + (uci->first_block * uc->blocksize);
}
uc->miss++;
return NULL;
}
int uwsgi_cache_del2(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_t index, uint16_t flags) {
struct uwsgi_cache_item *uci;
@@ -501,6 +483,10 @@ int uwsgi_cache_del2(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_
uci->expires = 0;
uc->n_items--;
if (uc->use_last_modified) {
uc->last_modified_at = uwsgi_now();
}
}
if (uc->nodes && ret == 0 && !(flags & UWSGI_CACHE_FLAG_LOCAL)) {
@@ -533,7 +519,8 @@ void uwsgi_cache_fix(struct uwsgi_cache *uc) {
}
}
uwsgi_log("[uwsgi-cache] restored %llu items\n", restored);
uc->n_items = restored;
uwsgi_log("[uwsgi-cache] restored %llu items\n", uc->n_items);
}
int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *val, uint64_t vallen, uint64_t expires, uint64_t flags) {
@@ -546,6 +533,7 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
uint8_t rollback_mode = 0;
int ret = -1;
time_t now = 0;
if (!keylen || !vallen)
return -1;
@@ -591,13 +579,13 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
uc->unused_blocks_stack_ptr++;
}
else if (rollback_mode == 2) {
uc->first_available_block--;
uc->first_available_block--;
}
goto end;
}
// mark used blocks;
uint64_t needed_blocks = cache_mark_blocks(uc, uci->first_block, vallen);
// optimize teh scan
uint64_t needed_blocks = cache_mark_blocks(uc, uci->first_block, vallen);
// optimize the scan
if (uc->blocks_bitmap_pos + (needed_blocks+1) > uc->blocks) {
uc->blocks_bitmap_pos = 0;
}
@@ -605,8 +593,10 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
uc->blocks_bitmap_pos = uci->first_block + needed_blocks + 1;
}
}
if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE))
expires += uwsgi_now();
if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE)) {
now = uwsgi_now();
expires += now;
}
uci->expires = expires;
uci->hash = uc->hash->func(key, keylen);
uci->hits = 0;
@@ -645,7 +635,8 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
else if (flags & UWSGI_CACHE_FLAG_UPDATE) {
uci = cache_item(index);
if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE)) {
expires += uwsgi_now();
now = uwsgi_now();
expires += now;
uci->expires = expires;
}
if (uc->blocks_bitmap) {
@@ -674,7 +665,11 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
uci->valsize = vallen;
ret = 0;
}
if (uc->use_last_modified) {
uc->last_modified_at = (now ? now : uwsgi_now());
}
if (uc->nodes && ret == 0 && !(flags & UWSGI_CACHE_FLAG_LOCAL)) {
cache_send_udp_command(uc, key, keylen, val, vallen, expires, 10);
}
@@ -952,6 +947,7 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
uc->nodes = uwsgi.cache_udp_node;
uc->udp_servers = uwsgi.cache_udp_server;
uc->store_sync = uwsgi.cache_store_sync;
uc->use_last_modified = (uint8_t) uwsgi.cache_use_last_modified;
if (uwsgi.cache_sync) {
uwsgi_string_new_list(&uc->sync_nodes, uwsgi.cache_sync);
@@ -971,6 +967,7 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
char *c_sync = NULL;
char *c_udp_servers = NULL;
char *c_bitmap = NULL;
char *c_use_last_modified = NULL;
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
"name", &c_name,
@@ -996,6 +993,7 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
"udpservers", &c_udp_servers,
"udpserver", &c_udp_servers,
"bitmap", &c_bitmap,
"lastmod", &c_use_last_modified,
NULL)) {
uwsgi_log("unable to parse cache definition\n");
exit(1);
@@ -1040,6 +1038,7 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
uc->use_blocks_bitmap = 1;
uc->max_item_size = uc->blocksize * uc->blocks;
}
if (c_use_last_modified) uc->use_last_modified = 1;
uc->store_sync = uwsgi.cache_store_sync;
if (c_store_sync) { uc->store_sync = uwsgi_n64(c_store_sync); }
@@ -1306,7 +1305,7 @@ static int cache_magic_send_and_manage(int fd, struct uwsgi_buffer *ub, char *st
return 0;
}
char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, char *cache) {
char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, uint64_t *expires, char *cache) {
struct uwsgi_cache_magic_context ucmc;
struct uwsgi_cache *uc = NULL;
char *cache_server = NULL;
@@ -1331,7 +1330,7 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, char *
// we have a local cache !!!
if (uc) {
uwsgi_rlock(uc->lock);
char *value = uwsgi_cache_get2(uc, key, keylen, vallen);
char *value = uwsgi_cache_get3(uc, key, keylen, vallen, expires);
if (!value) {
uwsgi_rwunlock(uc->lock);
return NULL;
@@ -1401,6 +1400,9 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, char *
ub->buf = NULL;
uwsgi_buffer_destroy(ub);
*vallen = ucmc.size;
if (expires) {
*expires = ucmc.expires;
}
return value;
}
@@ -1695,3 +1697,87 @@ int uwsgi_cache_magic_clear(char *cache) {
}
void uwsgi_cache_sync_from_nodes(struct uwsgi_cache *uc) {
struct uwsgi_string_list *usl = uc->sync_nodes;
while(usl) {
uwsgi_log("[cache-sync] getting cache dump from %s ...\n", usl->value);
int fd = uwsgi_connect(usl->value, 0, 0);
if (fd < 0) {
uwsgi_log("[cache-sync] unable to connect to the cache server\n");
goto next;
}
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size + uc->filesize);
ub->pos = 4;
if (uwsgi_buffer_append(ub, uc->name, uc->name_len)) {
uwsgi_buffer_destroy(ub);
close(fd);
goto next;
}
if (uwsgi_buffer_set_uh(ub, 111, 6)) {
uwsgi_buffer_destroy(ub);
close(fd);
goto next;
}
if (uwsgi_write_nb(fd, ub->buf, ub->pos, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uwsgi_buffer_destroy(ub);
uwsgi_log("[cache-sync] unable to write to the cache server\n");
close(fd);
goto next;
}
size_t rlen = ub->pos;
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uwsgi_buffer_destroy(ub);
uwsgi_log("[cache-sync] unable to read from the cache server\n");
close(fd);
goto next;
}
uwsgi_hooked_parse(ub->buf, ub->pos, cache_sync_hook, uc);
if (uwsgi_read_nb(fd, (char *) uc->items, uc->filesize, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uwsgi_buffer_destroy(ub);
close(fd);
uwsgi_log("[cache-sync] unable to read from the cache server\n");
goto next;
}
// reset the hashtable
memset(uc->hashtable, 0, sizeof(uint64_t) * UMAX16);
// re-fill the hashtable
uwsgi_cache_fix(uc);
uwsgi_buffer_destroy(ub);
close(fd);
break;
next:
if (!usl->next) {
exit(1);
}
uwsgi_log("[cache-sync] trying with the next sync node...\n");
usl = usl->next;
}
}
void uwsgi_cache_setup_nodes(struct uwsgi_cache *uc) {
struct uwsgi_string_list *usl = uc->nodes;
while(usl) {
char *port = strchr(usl->value, ':');
if (!port) {
uwsgi_log("[cache-udp-node] invalid udp address: %s\n", usl->value);
exit(1);
}
// no need to zero the memory, socket_to_in_addr will do that
struct sockaddr_in *sin = uwsgi_malloc(sizeof(struct sockaddr_in));
usl->custom = socket_to_in_addr(usl->value, port, 0, sin);
usl->custom_ptr = sin;
uwsgi_log("added udp node %s for cache \"%s\"\n", usl->value, uc->name);
usl = usl->next;
}
}
+33
View File
@@ -0,0 +1,33 @@
#include <uwsgi.h>
/*
pluggable configuration system
*/
extern struct uwsgi_server uwsgi;
struct uwsgi_configurator *uwsgi_register_configurator(char *name, void (*func)(char *, char **)) {
struct uwsgi_configurator *old_uc = NULL,*uc = uwsgi.configurators;
while(uc) {
if (!strcmp(uc->name, name)) {
return uc;
}
old_uc = uc;
uc = uc->next;
}
uc = uwsgi_calloc(sizeof(struct uwsgi_configurator));
uc->name = name;
uc->func = func;
if (old_uc) {
old_uc->next = uc;
}
else {
uwsgi.configurators = uc;
}
return uc;
}
+81
View File
@@ -0,0 +1,81 @@
#include <uwsgi.h>
/*
cookie management functions (mainly used by the internal routing subsystem)
*/
static char *check_cookie(char *cookie, uint16_t cookie_len, char *key, uint16_t keylen, uint16_t *vallen) {
uint16_t orig_cookie_len = cookie_len-1;
// first lstrip white spaces
char *ptr = cookie;
uint16_t i;
for(i=0;i<cookie_len;i++) {
if (isspace((int)ptr[i])) {
cookie++;
cookie_len--;
}
else {
break;
}
}
// then rstrip (skipping the first char...)
for(i=orig_cookie_len;i>0;i--) {
if (isspace((int)ptr[i])) {
cookie_len--;
}
else {
break;
}
}
// now search for the first equal sign
char *equal = memchr(cookie, '=', cookie_len);
if (!equal) return NULL;
if (uwsgi_strncmp(key, keylen, cookie, equal-cookie)) {
return NULL;
}
cookie_len -= (equal-cookie)+1;
if (cookie_len == 0) return NULL;
*vallen = cookie_len;
return equal+1;
}
char *uwsgi_get_cookie(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
uint16_t i;
char *cookie = wsgi_req->cookie;
uint16_t cookie_len = 0;
char *ptr = wsgi_req->cookie;
//start splitting by ;
for(i=0;i<wsgi_req->cookie_len;i++) {
if (!cookie) {
cookie = ptr + i;
}
if (ptr[i] == ';') {
char *value = check_cookie(cookie, cookie_len, key, keylen, vallen);
if (value) {
return value;
}
cookie_len = 0;
cookie = NULL;
}
else {
cookie_len++;
}
}
if (cookie_len > 0) {
char *value = check_cookie(cookie, cookie_len, key, keylen, vallen);
if (value) {
return value;
}
}
return NULL;
}
+172
View File
@@ -0,0 +1,172 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
struct uwsgi_cron *uwsgi_cron_add(char *crontab) {
int i;
struct uwsgi_cron *old_uc, *uc = uwsgi.crons;
if (!uc) {
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
uwsgi.crons = uc;
}
else {
old_uc = uc;
while (uc->next) {
uc = uc->next;
old_uc = uc;
}
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
uc = old_uc->next;
}
memset(uc, 0, sizeof(struct uwsgi_cron));
if (sscanf(crontab, "%d %d %d %d %d %n", &uc->minute, &uc->hour, &uc->day, &uc->month, &uc->week, &i) != 5) {
uwsgi_log("invalid cron syntax\n");
exit(1);
}
uc->command = crontab + i;
return uc;
}
void uwsgi_opt_add_cron(char *opt, char *value, void *foobar) {
uwsgi_cron_add(value);
}
#ifdef UWSGI_SSL
void uwsgi_opt_add_legion_cron(char *opt, char *value, void *foobar) {
char *space = strchr(value, ' ');
if (!space) {
uwsgi_log("invalid %s syntax, must be prefixed with a legion name\n", opt);
exit(1);
}
char *legion = uwsgi_concat2n(value, space-value, "", 0);
struct uwsgi_cron *uc = uwsgi_cron_add(space+1);
uc->legion = legion;
}
#endif
int uwsgi_signal_add_cron(uint8_t sig, int minute, int hour, int day, int month, int week) {
if (!uwsgi.master_process)
return -1;
uwsgi_lock(uwsgi.cron_table_lock);
if (ushared->cron_cnt < MAX_CRONS) {
ushared->cron[ushared->cron_cnt].sig = sig;
ushared->cron[ushared->cron_cnt].minute = minute;
ushared->cron[ushared->cron_cnt].hour = hour;
ushared->cron[ushared->cron_cnt].day = day;
ushared->cron[ushared->cron_cnt].month = month;
ushared->cron[ushared->cron_cnt].week = week;
ushared->cron_cnt++;
}
else {
uwsgi_log("you can register max %d cron !!!\n", MAX_CRONS);
uwsgi_unlock(uwsgi.cron_table_lock);
return -1;
}
uwsgi_unlock(uwsgi.cron_table_lock);
return 0;
}
void uwsgi_manage_signal_cron(time_t now) {
struct tm *uwsgi_cron_delta;
int i;
uwsgi_cron_delta = localtime(&now);
if (uwsgi_cron_delta) {
// fix month
uwsgi_cron_delta->tm_mon++;
uwsgi_lock(uwsgi.cron_table_lock);
for (i = 0; i < ushared->cron_cnt; i++) {
struct uwsgi_cron *ucron = &ushared->cron[i];
int run_task = uwsgi_cron_task_needs_execution(uwsgi_cron_delta, ucron->minute, ucron->hour, ucron->day, ucron->month, ucron->week);
if (run_task == 1) {
// date match, signal it ?
if (now - ucron->last_job >= 60) {
uwsgi_route_signal(ucron->sig);
ucron->last_job = now;
}
}
}
uwsgi_unlock(uwsgi.cron_table_lock);
}
else {
uwsgi_error("localtime()");
}
}
void uwsgi_manage_command_cron(time_t now) {
struct tm *uwsgi_cron_delta;
struct uwsgi_cron *current_cron = uwsgi.crons;
uwsgi_cron_delta = localtime(&now);
if (!uwsgi_cron_delta) {
uwsgi_error("uwsgi_manage_command_cron()/localtime()");
return;
}
// fix month
uwsgi_cron_delta->tm_mon++;
while (current_cron) {
#ifdef UWSGI_SSL
// check for legion cron
if (current_cron->legion) {
if (!uwsgi_legion_i_am_the_lord(current_cron->legion)) {
current_cron = current_cron->next;
continue;
}
}
#endif
int run_task = uwsgi_cron_task_needs_execution(uwsgi_cron_delta, current_cron->minute, current_cron->hour, current_cron->day, current_cron->month, current_cron->week);
if (run_task == 1) {
// date match, run command ?
if (now - current_cron->last_job >= 60) {
//call command
if (current_cron->command) {
if (current_cron->func) {
current_cron->func(current_cron, now);
}
else {
if (uwsgi_run_command(current_cron->command, NULL, -1) >= 0) {
uwsgi_log_verbose("[uwsgi-cron] running %s\n", current_cron->command);
}
}
}
current_cron->last_job = now;
}
}
current_cron = current_cron->next;
}
}
+12 -10
View File
@@ -208,18 +208,20 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
uwsgi_write_pidfile(ud->pidfile);
}
// /dev/null will became stdin
devnull = open("/dev/null", O_RDONLY);
if (devnull < 0) {
uwsgi_error("/dev/null open()");
exit(1);
}
if (devnull != 0) {
if (dup2(devnull, 0) < 0) {
uwsgi_error("dup2()");
if (!uwsgi.daemons_honour_stdin) {
// /dev/null will became stdin
devnull = open("/dev/null", O_RDONLY);
if (devnull < 0) {
uwsgi_error("/dev/null open()");
exit(1);
}
close(devnull);
if (devnull != 0) {
if (dup2(devnull, 0) < 0) {
uwsgi_error("dup2()");
exit(1);
}
close(devnull);
}
}
if (setsid() < 0) {
+280 -58
View File
@@ -122,19 +122,101 @@ void uwsgi_emperor_blacklist_remove(char *id) {
struct uwsgi_emperor_scanner *emperor_scanners;
static int has_extra_extension(char *name) {
struct uwsgi_string_list *usl = uwsgi.emperor_extra_extension;
while(usl) {
if (uwsgi_endswith(name, usl->value)) {
return 1;
}
usl = usl->next;
}
return 0;
}
int uwsgi_emperor_is_valid(char *name) {
if (uwsgi_endswith(name, ".xml") || uwsgi_endswith(name, ".ini") || uwsgi_endswith(name, ".yml") || uwsgi_endswith(name, ".yaml") || uwsgi_endswith(name, ".js") || uwsgi_endswith(name, ".json")) {
if (uwsgi_endswith(name, ".xml") || uwsgi_endswith(name, ".ini") || uwsgi_endswith(name, ".yml") || uwsgi_endswith(name, ".yaml") || uwsgi_endswith(name, ".js") || uwsgi_endswith(name, ".json") || has_extra_extension(name)) {
if (strlen(name) < 0xff) {
return 1;
}
}
return 0;
}
static char *emperor_check_on_demand_socket(char *filename) {
size_t len = 0;
if (uwsgi.emperor_on_demand_extension) {
char *tmp = uwsgi_concat2(filename, uwsgi.emperor_on_demand_extension);
int fd = open(tmp, O_RDONLY);
free(tmp);
if (fd < 0) return NULL;
char *ret = uwsgi_read_fd(fd, &len, 1);
close(fd);
// change the first non prinabel character to 0
size_t i;
for(i=0;i<len;i++) {
if (ret[i] < 32) {
ret[i] = 0;
break;
}
}
if (ret[0] == 0) {
free(ret);
return NULL;
}
return ret;
}
else if (uwsgi.emperor_on_demand_directory) {
// we need to build the socket path automagically
char *start_of_vassal_name = uwsgi_get_last_char(filename, '/');
if (!start_of_vassal_name) {
start_of_vassal_name = filename;
}
else {
start_of_vassal_name++;
}
char *last_dot = uwsgi_get_last_char(filename, '.');
if (!last_dot) return NULL;
return uwsgi_concat4n(uwsgi.emperor_on_demand_directory, strlen(uwsgi.emperor_on_demand_directory), "/", 1, start_of_vassal_name, last_dot - start_of_vassal_name, ".socket", 7);
}
else if (uwsgi.emperor_on_demand_exec) {
int cpipe[2];
if (pipe(cpipe)) {
uwsgi_error("emperor_check_on_demand_socket()pipe()");
return NULL;
}
char *cmd = uwsgi_concat4(uwsgi.emperor_on_demand_exec, " \"", filename, "\"");
int r = uwsgi_run_command(cmd, NULL, cpipe[1]);
free(cmd);
if (r < 0) {
close(cpipe[0]);
close(cpipe[1]);
return NULL;
}
char *ret = uwsgi_read_fd(cpipe[0], &len, 1);
close(cpipe[0]);
close(cpipe[1]);
// change the first non prinabel character to 0
size_t i;
for(i=0;i<len;i++) {
if (ret[i] < 32) {
ret[i] = 0;
break;
}
}
if (ret[0] == 0) {
free(ret);
return NULL;
}
return ret;
}
return NULL;
}
// this is the monitor for non-glob directories
void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
struct uwsgi_instance *ui_current;
@@ -160,10 +242,27 @@ void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
ui_current = emperor_get(de->d_name);
uid_t t_uid = st.st_uid;
gid_t t_gid = st.st_gid;
if (uwsgi.emperor_tyrant && uwsgi.emperor_tyrant_nofollow) {
struct stat lst;
if (lstat(de->d_name, &lst)) {
uwsgi_error("[emperor-tyrant]/lstat()");
if (ui_current) {
uwsgi_log("!!! availability of file %s changed. stopping the instance... !!!\n", de->d_name);
emperor_stop(ui_current);
}
continue;
}
t_uid = lst.st_uid;
t_gid = lst.st_gid;
}
if (ui_current) {
// check if uid or gid are changed, in such case, stop the instance
if (uwsgi.emperor_tyrant) {
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
if (t_uid != ui_current->uid || t_gid != ui_current->gid) {
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n", de->d_name);
emperor_stop(ui_current);
continue;
@@ -175,7 +274,9 @@ void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
}
}
else {
emperor_add(ues, de->d_name, st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
char *socket_name = emperor_check_on_demand_socket(de->d_name);
emperor_add(ues, de->d_name, st.st_mtime, NULL, 0, t_uid, t_gid, socket_name);
if (socket_name) free(socket_name);
}
}
closedir(dir);
@@ -235,10 +336,27 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
ui_current = emperor_get(g.gl_pathv[i]);
uid_t t_uid = st.st_uid;
gid_t t_gid = st.st_gid;
if (uwsgi.emperor_tyrant && uwsgi.emperor_tyrant_nofollow) {
struct stat lst;
if (lstat(g.gl_pathv[i], &lst)) {
uwsgi_error("[emperor-tyrant]/lstat()");
if (ui_current) {
uwsgi_log("!!! availability of file %s changed. stopping the instance... !!!\n", g.gl_pathv[i]);
emperor_stop(ui_current);
}
continue;
}
t_uid = lst.st_uid;
t_gid = lst.st_gid;
}
if (ui_current) {
// check if uid or gid are changed, in such case, stop the instance
if (uwsgi.emperor_tyrant) {
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
if (t_uid != ui_current->uid || t_gid != ui_current->gid) {
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n", g.gl_pathv[i]);
emperor_stop(ui_current);
continue;
@@ -250,7 +368,9 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
}
}
else {
emperor_add(ues, g.gl_pathv[i], st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
char *socket_name = emperor_check_on_demand_socket(g.gl_pathv[i]);
emperor_add(ues, g.gl_pathv[i], st.st_mtime, NULL, 0, t_uid, t_gid, socket_name);
if (socket_name) free(socket_name);
}
}
@@ -377,6 +497,22 @@ struct uwsgi_instance *emperor_get_by_fd(int fd) {
return NULL;
}
struct uwsgi_instance *emperor_get_by_socket_fd(int fd) {
struct uwsgi_instance *c_ui = ui;
while (c_ui->ui_next) {
c_ui = c_ui->ui_next;
// over engineering...
if (c_ui->on_demand_fd != -1 && c_ui->on_demand_fd == fd) {
return c_ui;
}
}
return NULL;
}
struct uwsgi_instance *emperor_get(char *name) {
@@ -430,6 +566,10 @@ void emperor_del(struct uwsgi_instance *c_ui) {
uwsgi.emperor_broodlord_count--;
}
if (c_ui->socket_name) {
free(c_ui->socket_name);
}
free(c_ui);
}
@@ -478,17 +618,10 @@ void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
uwsgi_log("[emperor] reload the uwsgi instance %s\n", c_ui->name);
}
void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, char *config, uint32_t config_size, uid_t uid, gid_t gid) {
void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, char *config, uint32_t config_size, uid_t uid, gid_t gid, char *socket_name) {
struct uwsgi_instance *c_ui = ui;
struct uwsgi_instance *n_ui = NULL;
pid_t pid;
char **vassal_argv;
char *uef;
char **uenvs;
int counter;
char *colon = NULL;
int i;
struct timeval tv;
#ifdef UWSGI_DEBUG
@@ -544,8 +677,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
c_ui = c_ui->ui_next;
}
n_ui = uwsgi_malloc(sizeof(struct uwsgi_instance));
memset(n_ui, 0, sizeof(struct uwsgi_instance));
n_ui = uwsgi_calloc(sizeof(struct uwsgi_instance));
if (config) {
n_ui->use_config = 1;
@@ -576,10 +708,60 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
n_ui->first_run = uwsgi_now();
n_ui->last_run = n_ui->first_run;
n_ui->on_demand_fd = -1;
if (socket_name) {
n_ui->socket_name = uwsgi_str(socket_name);
}
n_ui->pid = -1;
// ok here we check if we need to bind to the specified socket or continue with the activation
if (socket_name) {
char *tcp_port = strchr(socket_name, ':');
if (tcp_port) {
// disable deferred accept for this socket
int current_defer_accept = uwsgi.no_defer_accept;
uwsgi.no_defer_accept = 1;
n_ui->on_demand_fd = bind_to_tcp(socket_name, uwsgi.listen_queue, tcp_port);
uwsgi.no_defer_accept = current_defer_accept;
}
else {
n_ui->on_demand_fd = bind_to_unix(socket_name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
if (n_ui->on_demand_fd < 0) {
uwsgi_error("emperor_add()/bind()");
free(n_ui);
c_ui->ui_next = NULL;
return;
}
event_queue_add_fd_read(uwsgi.emperor_queue, n_ui->on_demand_fd);
uwsgi_log("[uwsgi-emperor] %s -> \"on demand\" instance detected, waiting for connections on socket \"%s\" ...\n", name, socket_name);
return;
}
if (uwsgi_emperor_vassal_start(n_ui)) {
// clear the vassal
free(n_ui);
c_ui->ui_next = NULL;
}
}
int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
int i;
char *colon = NULL;
int counter;
char **uenvs;
char *uef;
char **vassal_argv;
pid_t pid;
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe)) {
uwsgi_error("socketpair()");
goto clear;
return -1;
}
event_queue_add_fd_read(uwsgi.emperor_queue, n_ui->pipe[0]);
@@ -587,7 +769,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
if (n_ui->use_config) {
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe_config)) {
uwsgi_error("socketpair()");
goto clear;
return -1;
}
}
@@ -606,6 +788,11 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
n_ui->pid = pid;
// close the right side of the pipe
close(n_ui->pipe[1]);
// close the "on demand" socket
if (n_ui->on_demand_fd > -1) {
close(n_ui->on_demand_fd);
n_ui->on_demand_fd = -1;
}
if (n_ui->use_config) {
close(n_ui->pipe_config[1]);
}
@@ -625,13 +812,13 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
}
}
return;
return 0;
}
else {
if (uwsgi.emperor_tyrant) {
uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) uid, (int) gid, name);
if (setgid(gid)) {
uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) n_ui->uid, (int) n_ui->gid, n_ui->name);
if (setgid(n_ui->gid)) {
uwsgi_error("setgid()");
exit(1);
}
@@ -640,7 +827,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
exit(1);
}
if (setuid(uid)) {
if (setuid(n_ui->uid)) {
uwsgi_error("setuid()");
exit(1);
}
@@ -678,15 +865,16 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
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 (!strncmp(*uenvs, "UWSGI_VASSAL_", 13) && strchr(*uenvs, '=')) {
char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0), *ne;
if (unsetenv(oe)) {
uwsgi_error("unsetenv()");
free(oe);
break;
}
free(oe);
ne = uwsgi_concat2("UWSGI_", *uenvs + 13);
#ifdef UWSGI_DEBUG
uwsgi_log("putenv %s\n", ne);
#endif
@@ -720,7 +908,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
vassal_argv[0] = uwsgi.binary_path;
if (uwsgi.emperor_broodlord) {
colon = strchr(name, ':');
colon = strchr(n_ui->name, ':');
if (colon) {
colon[0] = 0;
}
@@ -728,34 +916,43 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
// initialize to a default value
vassal_argv[1] = "--inherit";
if (!strcmp(name + (strlen(name) - 4), ".xml"))
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".xml"))
vassal_argv[1] = "--xml";
if (!strcmp(name + (strlen(name) - 4), ".ini"))
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".ini"))
vassal_argv[1] = "--ini";
if (!strcmp(name + (strlen(name) - 4), ".yml"))
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".yml"))
vassal_argv[1] = "--yaml";
if (!strcmp(name + (strlen(name) - 5), ".yaml"))
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".yaml"))
vassal_argv[1] = "--yaml";
if (!strcmp(name + (strlen(name) - 3), ".js"))
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 3), ".js"))
vassal_argv[1] = "--json";
if (!strcmp(name + (strlen(name) - 5), ".json"))
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".json"))
vassal_argv[1] = "--json";
struct uwsgi_string_list *usl = uwsgi.emperor_extra_extension;
while(usl) {
if (uwsgi_endswith(n_ui->name, usl->value)) {
vassal_argv[1] = "--config";
break;
}
usl = usl->next;
}
if (colon) {
colon[0] = ':';
}
vassal_argv[2] = name;
vassal_argv[2] = n_ui->name;
if (uwsgi.emperor_magic_exec) {
if (!access(name, R_OK | X_OK)) {
vassal_argv[2] = uwsgi_concat2("exec://", name);
if (!access(n_ui->name, R_OK | X_OK)) {
vassal_argv[2] = uwsgi_concat2("exec://", n_ui->name);
}
}
if (n_ui->use_config) {
vassal_argv[2] = uwsgi_concat2("emperor://", name);
vassal_argv[2] = uwsgi_concat2("emperor://", n_ui->name);
}
counter = 3;
@@ -768,18 +965,29 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
}
vassal_argv[counter] = NULL;
// disable stdin
int stdin_fd = open("/dev/null", O_RDONLY);
if (stdin_fd < 0) {
uwsgi_error_open("/dev/null");
exit(1);
// disable stdin OR map it to the "on demand" socket
if (n_ui->on_demand_fd > -1) {
if (n_ui->on_demand_fd != 0) {
if (dup2(n_ui->on_demand_fd, 0) < 0) {
uwsgi_error("dup2()");
exit(1);
}
close(n_ui->on_demand_fd);
}
}
if (stdin_fd != 0) {
if (dup2(stdin_fd, 0) < 0) {
uwsgi_error("dup2()");
else {
int stdin_fd = open("/dev/null", O_RDONLY);
if (stdin_fd < 0) {
uwsgi_error_open("/dev/null");
exit(1);
}
close(stdin_fd);
if (stdin_fd != 0) {
if (dup2(stdin_fd, 0) < 0) {
uwsgi_error("dup2()");
exit(1);
}
close(stdin_fd);
}
}
// close all of the unneded fd
@@ -813,11 +1021,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
exit(UWSGI_EXILE_CODE);
}
clear:
free(n_ui);
c_ui->ui_next = NULL;
return -1;
}
void uwsgi_imperial_monitor_glob_init(struct uwsgi_emperor_scanner *ues) {
@@ -975,6 +1179,8 @@ void emperor_loop() {
char notification_message[64];
struct rlimit rl;
uwsgi.disable_nuclear_blast = 1;
uwsgi.emperor_stats_fd = -1;
if (uwsgi.emperor_pidfile) {
@@ -1087,14 +1293,24 @@ void emperor_loop() {
else if (byte == 30 && uwsgi.emperor_broodlord > 0 && uwsgi.emperor_broodlord_count < uwsgi.emperor_broodlord) {
uwsgi_log("[emperor] going in broodlord mode: launching zergs for %s\n", ui_current->name);
char *zerg_name = uwsgi_concat3(ui_current->name, ":", "zerg");
emperor_add(ui_current->scanner, zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid);
// here we discard socket name as broodlord/zerg cannot be on demand
emperor_add(ui_current->scanner, zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid, NULL);
free(zerg_name);
}
}
}
else {
uwsgi_log("[emperor] unrecognized vassal event on fd %d\n", interesting_fd);
close(interesting_fd);
ui_current = emperor_get_by_socket_fd(interesting_fd);
if (ui_current) {
event_queue_del_fd(uwsgi.emperor_queue, ui_current->on_demand_fd, event_queue_read());
if (uwsgi_emperor_vassal_start(ui_current)) {
emperor_del(ui_current);
}
}
else {
uwsgi_log("[emperor] unrecognized vassal event on fd %d\n", interesting_fd);
close(interesting_fd);
}
}
}
@@ -1120,7 +1336,9 @@ void emperor_loop() {
has_children = 0;
while (ui_current->ui_next) {
ui_current = ui_current->ui_next;
has_children++;
if (ui_current->pid > -1) {
has_children++;
}
}
if (uwsgi.notify) {
@@ -1172,7 +1390,7 @@ void emperor_loop() {
}
else {
// UNSAFE
emperor_add(ui_current->scanner, ui_current->name, ui_current->last_mod, ui_current->config, ui_current->config_len, ui_current->uid, ui_current->gid);
emperor_add(ui_current->scanner, ui_current->name, ui_current->last_mod, ui_current->config, ui_current->config_len, ui_current->uid, ui_current->gid, ui_current->socket_name);
emperor_del(ui_current);
}
break;
@@ -1266,7 +1484,7 @@ void emperor_send_stats(int fd) {
if (uwsgi_stats_keyval_comma(us, "id", c_ui->name))
goto end0;
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) c_ui->pid))
if (uwsgi_stats_keyslong_comma(us, "pid", (long long) c_ui->pid))
goto end0;
if (uwsgi_stats_keylong_comma(us, "born", (unsigned long long) c_ui->born))
goto end0;
@@ -1285,6 +1503,9 @@ void emperor_send_stats(int fd) {
if (uwsgi_stats_keylong_comma(us, "zerg", (unsigned long long) c_ui->zerg))
goto end0;
if (uwsgi_stats_keyval_comma(us, "on_demand", c_ui->socket_name ? c_ui->socket_name : ""))
goto end0;
if (uwsgi_stats_keylong_comma(us, "uid", (unsigned long long) c_ui->uid))
goto end0;
if (uwsgi_stats_keylong_comma(us, "gid", (unsigned long long) c_ui->gid))
@@ -1403,6 +1624,7 @@ void uwsgi_emperor_start() {
else {
uwsgi.emperor_pid = uwsgi_fork("uWSGI Emperor");
}
if (uwsgi.emperor_pid < 0) {
uwsgi_error("pid()");
exit(1);
@@ -1436,7 +1658,7 @@ void uwsgi_check_emperor() {
}
void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char *config, time_t ts, uid_t uid, gid_t gid) {
void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char *config, time_t ts, uid_t uid, gid_t gid, char *socket_name) {
if (!uwsgi_emperor_is_valid(name))
return;
@@ -1473,6 +1695,6 @@ void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char
new_config = uwsgi_str(config);
new_config_len = strlen(new_config);
}
emperor_add(ues, name, ts, new_config, new_config_len, uid, gid);
emperor_add(ues, name, ts, new_config, new_config_len, uid, gid, socket_name);
}
}
+241 -14
View File
@@ -2,6 +2,233 @@
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_EVENT_USE_POLL
#define UWSGI_EVENT_IN POLLIN
#define UWSGI_EVENT_OUT POLLOUT
int uwsgi_poll_event_queue_max = 0;
struct uwsgi_poll_event {
int nevents;
int max_events;
pthread_mutex_t lock;
struct pollfd *poll;
};
struct uwsgi_poll_event **uwsgi_poll_event_queue;
// all of the public functions must be heavy locked
static int uwsgi_poll_fd_is_registered(struct uwsgi_poll_event *upe, int fd) {
int i;
for(i=0;i<upe->nevents;i++) {
if (upe->poll[i].fd == fd) {
return 1;
}
}
return 0;
}
static int uwsgi_poll_fd_add(struct uwsgi_poll_event *upe, int fd, int event) {
int pos = upe->nevents;
if (pos > upe->max_events) return -1;
upe->poll[pos].fd = fd;
upe->poll[pos].events = event;
upe->nevents++;
return 0;
}
static int uwsgi_poll_fd_del(struct uwsgi_poll_event *upe, int fd) {
int i;
for(i=0;i<upe->nevents;i++) {
if (upe->poll[i].fd == fd) {
if (i < upe->nevents-1) {
memcpy(&upe->poll[i], &upe->poll[i+1], sizeof(struct uwsgi_poll_event) * (upe->nevents - (i+1)));
}
upe->nevents--;
return 0;
}
}
return -1;
}
static void uwsgi_poll_queue_rebuild(struct uwsgi_poll_event *upe) {
// we need to check if some file descriptor is no more valid
int i;
for(i=0;i<upe->nevents;i++) {
if (!uwsgi_valid_fd(upe->poll[i].fd)) {
uwsgi_poll_fd_del(upe, upe->poll[i].fd);
}
}
}
int event_queue_wait(int eq, int timeout, int *interesting_fd) {
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
pthread_mutex_lock(&upe->lock);
uwsgi_poll_queue_rebuild(upe);
int ret = poll(upe->poll, upe->nevents, timeout * 1000);
if (ret > 0) {
int i;
for(i=0;i<upe->nevents;i++) {
if (upe->poll[i].revents) {
*interesting_fd = upe->poll[i].fd;
pthread_mutex_unlock(&upe->lock);
return 1;
}
}
}
pthread_mutex_unlock(&upe->lock);
return ret;
}
int event_queue_init() {
if (!uwsgi_poll_event_queue) {
uwsgi_poll_event_queue = uwsgi_calloc(sizeof(struct uwsgi_poll_event *) * uwsgi.max_fd);
}
int eq = uwsgi_poll_event_queue_max;
uwsgi_poll_event_queue[eq] = uwsgi_calloc(sizeof(struct uwsgi_poll_event));
uwsgi_poll_event_queue_max++;
uwsgi_poll_event_queue[eq]->poll = uwsgi_malloc(sizeof(struct pollfd) * uwsgi.max_fd);
uwsgi_poll_event_queue[eq]->max_events = uwsgi.max_fd;
pthread_mutex_init(&uwsgi_poll_event_queue[eq]->lock, NULL);
return eq;
}
void *event_queue_alloc(int nevents) {
return uwsgi_calloc(sizeof(struct pollfd) * nevents);
}
int event_queue_interesting_fd_is_read(void *events, int id) {
struct pollfd *pevents = (struct pollfd *)events;
struct pollfd *upoll = &pevents[id];
if (upoll->revents & POLLIN) {
return 1;
}
return 0;
}
int event_queue_fd_write_to_readwrite(int eq, int fd) {
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
pthread_mutex_lock(&upe->lock);
int i;
for(i=0;i<upe->nevents;i++) {
if (upe->poll[i].fd == fd) {
upe->poll[i].events = POLLIN|POLLOUT;
pthread_mutex_unlock(&upe->lock);
return 0;
}
}
pthread_mutex_unlock(&upe->lock);
return -1;
}
int event_queue_fd_read_to_readwrite(int eq, int fd) {
return event_queue_fd_write_to_readwrite(eq, fd);
}
int event_queue_interesting_fd_is_write(void *events, int id) {
struct pollfd *pevents = (struct pollfd *)events;
struct pollfd *upoll = &pevents[id];
if (upoll->revents & POLLOUT) {
return 1;
}
return 0;
}
int event_queue_add_fd_read(int eq, int fd) {
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
pthread_mutex_lock(&upe->lock);
if (uwsgi_poll_fd_is_registered(upe, fd)) {
pthread_mutex_unlock(&upe->lock);
return 0;
}
int ret = uwsgi_poll_fd_add(upe, fd, POLLIN);
pthread_mutex_unlock(&upe->lock);
return ret;
}
int event_queue_add_fd_write(int eq, int fd) {
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
pthread_mutex_lock(&upe->lock);
if (uwsgi_poll_fd_is_registered(upe, fd)) {
pthread_mutex_unlock(&upe->lock);
return 0;
}
int ret = uwsgi_poll_fd_add(upe, fd, POLLOUT);
pthread_mutex_unlock(&upe->lock);
return ret;
}
int event_queue_del_fd(int eq, int fd, int event) {
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
pthread_mutex_lock(&upe->lock);
int ret = uwsgi_poll_fd_del(upe, fd);
pthread_mutex_unlock(&upe->lock);
return ret;
}
int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
pthread_mutex_lock(&upe->lock);
uwsgi_poll_queue_rebuild(upe);
int ret = poll(upe->poll, upe->nevents, timeout * 1000);
int cnt = 0;
if (ret > 0) {
int i;
for(i=0;i<upe->nevents;i++) {
if (upe->poll[i].revents) {
struct pollfd *pevents = (struct pollfd *)events;
struct pollfd *upoll = &pevents[cnt];
upoll->fd = upe->poll[i].fd;
upoll->revents = upe->poll[i].revents;
upoll->events = upe->poll[i].events;
cnt++;
}
}
}
pthread_mutex_unlock(&upe->lock);
if (ret <= 0) return ret;
return cnt;
}
int event_queue_interesting_fd_has_error(void *events, int id) {
struct pollfd *pevents = (struct pollfd *)events;
struct pollfd *upoll = &pevents[id];
if (upoll->revents & POLLERR || upoll->revents & POLLHUP || upoll->revents & POLLNVAL) {
return 1;
}
return 0;
}
int event_queue_interesting_fd(void *events, int id) {
struct pollfd *pevents = (struct pollfd *)events;
struct pollfd *upoll = &pevents[id];
return upoll->fd;
}
int event_queue_fd_write_to_read(int eq, int fd) {
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
pthread_mutex_lock(&upe->lock);
int i;
for(i=0;i<upe->nevents;i++) {
if (upe->poll[i].fd == fd) {
upe->poll[i].events = POLLIN;
pthread_mutex_unlock(&upe->lock);
return 0;
}
}
pthread_mutex_unlock(&upe->lock);
return -1;
}
int event_queue_fd_read_to_write(int eq, int fd) {
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
pthread_mutex_lock(&upe->lock);
int i;
for(i=0;i<upe->nevents;i++) {
if (upe->poll[i].fd == fd) {
upe->poll[i].events = POLLOUT;
pthread_mutex_unlock(&upe->lock);
return 0;
}
}
pthread_mutex_unlock(&upe->lock);
return -1;
}
#endif
#ifdef UWSGI_EVENT_USE_PORT
#include <port.h>
@@ -33,7 +260,7 @@ int event_queue_del_fd(int eq, int fd, int event) {
int event_queue_fd_write_to_read(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
uwsgi_error("port_associate");
return -1;
}
@@ -44,7 +271,7 @@ int event_queue_fd_write_to_read(int eq, int fd) {
int event_queue_fd_read_to_write(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
uwsgi_error("port_associate");
return -1;
}
@@ -55,7 +282,7 @@ int event_queue_fd_read_to_write(int eq, int fd) {
int event_queue_fd_readwrite_to_read(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
uwsgi_error("port_associate");
return -1;
}
@@ -66,7 +293,7 @@ int event_queue_fd_readwrite_to_read(int eq, int fd) {
int event_queue_fd_readwrite_to_write(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
uwsgi_error("port_associate");
return -1;
}
@@ -77,7 +304,7 @@ int event_queue_fd_readwrite_to_write(int eq, int fd) {
int event_queue_fd_write_to_readwrite(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, NULL)) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, (void *)((long) eq))) {
uwsgi_error("port_associate");
return -1;
}
@@ -88,7 +315,7 @@ int event_queue_fd_write_to_readwrite(int eq, int fd) {
int event_queue_fd_read_to_readwrite(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, NULL)) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, (void *)((long) eq))) {
uwsgi_error("port_associate");
return -1;
}
@@ -124,7 +351,7 @@ int event_queue_interesting_fd_is_write(void *events, int id) {
int event_queue_add_fd_read(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
uwsgi_error("port_associate");
return -1;
}
@@ -134,7 +361,7 @@ int event_queue_add_fd_read(int eq, int fd) {
int event_queue_add_fd_write(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
uwsgi_error("port_associate");
return -1;
}
@@ -154,7 +381,7 @@ int event_queue_interesting_fd(void *events, int id) {
}
int fd = (int) pe[id].portev_object;
int eq = (int) pe[id].portev_user;
int eq = (long) pe[id].portev_user;
if (pe[id].portev_events == POLLOUT) {
event_queue_add_fd_write(eq, fd);
@@ -196,7 +423,7 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
port_event_t *pe_i = &pe[i];
if (pe_i->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_i->portev_source, pe_i->portev_object, pe_i->portev_events, NULL)) {
if (port_associate(eq, pe_i->portev_source, pe_i->portev_object, pe_i->portev_events, (void *)((long) eq))) {
uwsgi_error("port_associate");
}
}
@@ -222,16 +449,16 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
ret = port_get(eq, &pe, NULL);
}
if (ret < 0) {
if (errno != ETIME) {
if (errno == ETIME) return 0;
if (errno != EINTR) {
uwsgi_error("port_get()");
return -1;
}
return 0;
return -1;
}
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)) {
if (port_associate(eq, pe.portev_source, pe.portev_object, pe.portev_events, (void *)((long) eq))) {
uwsgi_error("port_associate");
}
}
+3 -3
View File
@@ -322,7 +322,7 @@ void uwsgi_manage_exception(struct wsgi_request *wsgi_req,int catch) {
if (do_exit) goto check_catch;
if (wsgi_req && uwsgi.exception_handlers_instance) {
if (uwsgi.exception_handlers_instance) {
struct uwsgi_buffer *ehi = uwsgi_exception_handler_object(wsgi_req);
if (ehi) {
uwsgi_exception_run_handlers(ehi);
@@ -442,7 +442,7 @@ static void uwsgi_exception_handler_thread_loop(struct uwsgi_thread *ut) {
int interesting_fd = -1;
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
if (ret > 0) {
ssize_t len = read(ut->pipe[1], buf, uwsgi.alarm_msg_size + sizeof(long));
ssize_t len = read(ut->pipe[1], buf, uwsgi.exception_handler_msg_size + sizeof(long));
if (len > (ssize_t)(sizeof(long) + 1)) {
size_t msg_size = len - sizeof(long);
char *msg = buf + sizeof(long);
@@ -488,7 +488,7 @@ void uwsgi_exception_setup_handlers() {
}
void uwsgi_exceptions_handler_thread_start() {
if (!uwsgi.exception_handlers_instance) return;
// start the exception_handler_thread
uwsgi.exception_handler_thread = uwsgi_thread_new(uwsgi_exception_handler_thread_loop);
if (!uwsgi.exception_handler_thread) {
+7
View File
@@ -28,10 +28,17 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop) (int, void *), v
ug->fullname = fullname;
ug->data = data;
#if defined(SOCK_SEQPACKET) && defined(__linux__)
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, ug->internal_subscription_pipe)) {
#else
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, ug->internal_subscription_pipe)) {
#endif
uwsgi_error("socketpair()");
}
uwsgi_socket_nb(ug->internal_subscription_pipe[0]);
uwsgi_socket_nb(ug->internal_subscription_pipe[1]);
if (!uwsgi.master_process)
gateway_respawn(ushared->gateways_cnt);
+14 -6
View File
@@ -1,6 +1,4 @@
#ifdef UWSGI_INI
#include "uwsgi.h"
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
@@ -9,6 +7,8 @@ extern struct uwsgi_server uwsgi;
This memory must not be freed for all the server lifecycle
*/
static char *last_file = NULL;
void ini_rstrip(char *line) {
off_t i;
@@ -106,13 +106,23 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
if (colon[1] != 0) {
section_asked = colon + 1;
}
if (colon == file) {
file = last_file;
}
}
if (file[0] != 0) {
if (file[0] != 0 && file != last_file) {
uwsgi_log_initial("[uWSGI] getting INI configuration from %s\n", file);
}
ini = uwsgi_open_and_read(file, &len, 1, magic_table);
if (file != last_file) {
if (last_file) {
free(last_file);
}
last_file = uwsgi_str(file);
}
while (len) {
ini_line = ini_get_line(ini, len);
@@ -157,5 +167,3 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
}
#endif
+78 -6
View File
@@ -770,10 +770,10 @@ timeout:
// check if an fd is valid
int uwsgi_valid_fd(int fd) {
int ret = fcntl(fd, F_GETFL);
if (ret == 0) {
return 1;
if (ret == -1) {
return 0;
}
return 0;
return 1;
}
void uwsgi_close_all_fds(void) {
@@ -955,6 +955,8 @@ readok2:
int uwsgi_proxy_nb(struct wsgi_request *wsgi_req, char *addr, struct uwsgi_buffer *ub, size_t remains, int timeout) {
struct uwsgi_buffer *headers = NULL;
int fd = uwsgi_connect(addr, 0, 1);
if (fd < 0) {
return -1;
@@ -988,21 +990,91 @@ int uwsgi_proxy_nb(struct wsgi_request *wsgi_req, char *addr, struct uwsgi_buffe
}
// read the response
headers = uwsgi_buffer_new(8192);
// max 64k headers
ub->limit = UMAX16;
for(;;) {
char buf[8192];
ssize_t rlen = uwsgi_read_true_nb(fd, buf, 8192, timeout);
if (rlen > 0) {
if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) {
break;
}
if (headers) {
if (uwsgi_buffer_append(headers, buf, rlen)) {
goto end;
}
// check if we have a full HTTP response
if (uwsgi_is_full_http(headers)) {
int ret = uwsgi_blob_to_response(wsgi_req, headers->buf, headers->pos);
if (ret) continue;
uwsgi_buffer_destroy(headers);
headers = NULL;
}
}
else {
if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) {
break;
}
}
continue;
}
break;
}
if (headers) uwsgi_buffer_destroy(headers);
close(fd);
return 0;
end:
if (headers) uwsgi_buffer_destroy(headers);
close(fd);
return -1;
}
void uwsgi_file_write_do(struct uwsgi_string_list *usl) {
struct uwsgi_string_list *fl = usl;
while(fl) {
char *equal = strchr(fl->value, '=');
if (equal) {
*equal = 0;
FILE *f = fopen(fl->value, "w");
if (!f) {
uwsgi_error_open("uwsgi_file_write_do()");
exit(1);
}
uwsgi_log("writing \"%s\" to \"%s\" ...\n", equal+1, fl->value);
if (fprintf(f, "%s\n", equal+1) <= 0 || ferror(f) || fclose(f)) {
uwsgi_error("uwsgi_file_write_do()");
exit(1);
}
}
else {
uwsgi_log("unable to write empty value for \"%s\"\n", fl->value);
exit(1);
}
*equal = '=';
fl = fl->next;
}
}
int uwsgi_fd_is_safe(int fd) {
int i;
for(i=0;i<uwsgi.safe_fds_cnt;i++) {
if (uwsgi.safe_fds[i] == fd) {
return 1;
}
}
return 0;
}
void uwsgi_add_safe_fd(int fd) {
// check if the fd is already safe
if (uwsgi_fd_is_safe(fd)) return;
size_t len = sizeof(int) * (uwsgi.safe_fds_cnt+1);
int *tmp = realloc(uwsgi.safe_fds, len);
if (!tmp) {
uwsgi_error("uwsgi_add_safe_fd()/realloc()");
exit(1);
}
uwsgi.safe_fds = tmp;
uwsgi.safe_fds[uwsgi.safe_fds_cnt] = fd;
uwsgi.safe_fds_cnt++;
}
+190 -34
View File
@@ -81,6 +81,37 @@ void uwsgi_parse_legion(char *key, uint16_t keylen, char *value, uint16_t vallen
}
}
// this function is called when a node is added or removed (heavy locking is needed)
static void legion_rebuild_scrolls(struct uwsgi_legion *ul) {
uint64_t max_size = ul->scrolls_max_size;
// first, try to add myself
if (ul->scroll_len + (uint64_t) 2 > max_size) {
uwsgi_log("[DANGER] you have configured a too much tiny buffer for the scrolls list !!! tune it with --legion-scroll-list-max-size\n");
ul->scroll_len = 0;
return;
}
char *ptr = ul->scrolls;
*ptr ++= (uint8_t) (ul->scroll_len & 0xff);
*ptr ++= (uint8_t) ((ul->scroll_len >> 8) &0xff);
memcpy(ptr, ul->scroll, ul->scroll_len); ptr += ul->scroll_len;
ul->scrolls_len = 2 + ul->scroll_len;
// ok start adding nodes;
struct uwsgi_legion_node *uln = ul->nodes_head;
while(uln) {
if (ul->scrolls_len + 2 + uln->scroll_len > max_size) {
uwsgi_log("[DANGER] you have configured a too much tiny buffer for the scrolls list !!! tune it with --legion-scroll-list-max-size\n");
return;
}
*ptr ++= (uint8_t) (uln->scroll_len & 0xff);
*ptr ++= (uint8_t) ((uln->scroll_len >> 8) &0xff);
memcpy(ptr, uln->scroll, uln->scroll_len); ptr += uln->scroll_len;
ul->scrolls_len += 2 + uln->scroll_len;
uln = uln->next;
}
}
// critical section (remember to lock when you use it)
struct uwsgi_legion_node *uwsgi_legion_add_node(struct uwsgi_legion *ul, uint16_t valor, char *name, uint16_t name_len, char *uuid) {
@@ -104,6 +135,7 @@ struct uwsgi_legion_node *uwsgi_legion_add_node(struct uwsgi_legion *ul, uint16_
ul->nodes_head = node;
}
return node;
@@ -141,6 +173,8 @@ void uwsgi_legion_remove_node(struct uwsgi_legion *ul, struct uwsgi_legion_node
}
free(node);
legion_rebuild_scrolls(ul);
}
struct uwsgi_legion_node *uwsgi_legion_get_node(struct uwsgi_legion *ul, uint64_t valor, char *name, uint16_t name_len, char *uuid) {
@@ -169,14 +203,22 @@ static void legions_check_nodes() {
struct uwsgi_legion_node *node = legion->nodes_head;
while (node) {
if (now - node->last_seen > uwsgi.legion_tolerance) {
struct uwsgi_legion_node *tmp_node = node;
node = node->next;
uwsgi_log("[uwsgi-legion] node: %.*s valor: %llu uuid: %.*s left Legion %s\n", tmp_node->name_len, tmp_node->name, tmp_node->valor, 36, tmp_node->uuid, legion->legion);
uwsgi_log("[uwsgi-legion] %s: %.*s valor: %llu uuid: %.*s left Legion %s\n", tmp_node->valor > 0 ? "node" : "arbiter", tmp_node->name_len, tmp_node->name, tmp_node->valor, 36, tmp_node->uuid, legion->legion);
uwsgi_wlock(legion->lock);
uwsgi_legion_remove_node(legion, tmp_node);
uwsgi_rwunlock(legion->lock);
// trigger node_left hooks
struct uwsgi_string_list *usl = legion->node_left_hooks;
while (usl) {
int ret = uwsgi_legion_action_call("node_left", legion, usl);
if (ret) {
uwsgi_log("[uwsgi-legion] ERROR, node_left hook returned: %d\n", ret);
}
usl = usl->next;
}
continue;
}
node = node->next;
@@ -190,12 +232,12 @@ struct uwsgi_legion_node *uwsgi_legion_get_lord(struct uwsgi_legion *);
static void legions_report_quorum(struct uwsgi_legion *ul, uint64_t best_valor, char *best_uuid, int votes) {
struct uwsgi_legion_node *nodes = ul->nodes_head;
uwsgi_log("\n[uwsgi-legion] --- WE HAVE QUORUM FOR LEGION %s !!! (valor: %llu uuid: %.*s checksum: %llu votes: %d) ---\n", ul->legion, best_valor, 36, best_uuid, ul->checksum, votes);
uwsgi_log("[uwsgi-legion] --- WE HAVE QUORUM FOR LEGION %s !!! (valor: %llu uuid: %.*s checksum: %llu votes: %d) ---\n", ul->legion, best_valor, 36, best_uuid, ul->checksum, votes);
while (nodes) {
uwsgi_log("[uwsgi-legion-node] node: %.*s valor: %llu uuid: %.*s last_seen: %d vote_valor: %llu vote_uuid: %.*s\n", nodes->name_len, nodes->name, nodes->valor, 36, nodes->uuid, nodes->last_seen, nodes->lord_valor, 36, nodes->lord_uuid);
uwsgi_log("[uwsgi-legion-node] %s: %.*s valor: %llu uuid: %.*s last_seen: %d vote_valor: %llu vote_uuid: %.*s\n", nodes->valor > 0 ? "node" : "arbiter", nodes->name_len, nodes->name, nodes->valor, 36, nodes->uuid, nodes->last_seen, nodes->lord_valor, 36, nodes->lord_uuid);
nodes = nodes->next;
}
uwsgi_log("[uwsgi-legion] --- END OF QUORUM REPORT ---\n\n");
uwsgi_log("[uwsgi-legion] --- END OF QUORUM REPORT ---\n");
}
uint64_t uwsgi_legion_checksum(struct uwsgi_legion *ul) {
@@ -231,12 +273,17 @@ static void legions_check_nodes_step2() {
best_valor = node->valor;
memcpy(best_uuid, node->uuid, 36);
}
else {
// go on if i am not an arbiter
else if (ul->valor > 0) {
// no potential Lord is available, i will propose myself
best_valor = ul->valor;
memcpy(best_uuid, ul->uuid, 36);
i_am_the_best = 1;
}
else {
// empty lord
memset(best_uuid, 0, 36);
}
// calculate the checksum
uint64_t new_checksum = uwsgi_legion_checksum(ul);
@@ -268,6 +315,18 @@ static void legions_check_nodes_step2() {
// we have quorum !!!
if (votes > 0 && votes >= ul->quorum) {
if (!ul->joined) {
// triggering join hooks
struct uwsgi_string_list *usl = ul->join_hooks;
while (usl) {
int ret = uwsgi_legion_action_call("join", ul, usl);
if (ret) {
uwsgi_log("[uwsgi-legion] ERROR, join hook returned: %d\n", ret);
}
usl = usl->next;
}
ul->joined = 1;
}
// something changed ???
if (ul->changed) {
legions_report_quorum(ul, best_valor, best_uuid, votes);
@@ -303,9 +362,9 @@ static void legions_check_nodes_step2() {
if (ul->i_am_the_lord) {
uwsgi_log("[uwsgi-legion] a new Lord (valor: %llu uuid: %.*s) raised for Legion %s...\n", ul->lord_valor, 36, ul->lord_uuid, ul->legion);
if (ul->lord_scroll_len > 0) {
uwsgi_log("*********** The New Lord Scroll ***********\n\n");
uwsgi_log("*********** The New Lord Scroll ***********\n");
uwsgi_log("%.*s\n", ul->lord_scroll_len, ul->lord_scroll);
uwsgi_log("\n*********** End of the New Lord Scroll ***********\n\n");
uwsgi_log("*********** End of the New Lord Scroll ***********\n");
}
// no more lord, trigger unlord hooks
struct uwsgi_string_list *usl = ul->unlord_hooks;
@@ -322,6 +381,20 @@ static void legions_check_nodes_step2() {
}
else if (votes > 0 && votes < ul->quorum && (uwsgi_now() - ul->last_warning >= 60)) {
uwsgi_log("[uwsgi-legion] no quorum: only %d vote(s) for Legion %s, %d needed to elect a Lord\n", votes, ul->legion, ul->quorum);
// no more quorum, leave the Lord state
if (ul->i_am_the_lord) {
uwsgi_log("[uwsgi-legion] i cannot be The Lord of The Legion %s without a quorum ...\n", ul->legion);
// no more lord, trigger unlord hooks
struct uwsgi_string_list *usl = ul->unlord_hooks;
while (usl) {
int ret = uwsgi_legion_action_call("unlord", ul, usl);
if (ret) {
uwsgi_log("[uwsgi-legion] ERROR, unlord hook returned: %d\n", ret);
}
usl = usl->next;
}
ul->i_am_the_lord = 0;
}
ul->last_warning = uwsgi_now();
}
@@ -341,6 +414,8 @@ struct uwsgi_legion_node *uwsgi_legion_get_lord(struct uwsgi_legion *ul) {
struct uwsgi_legion_node *nodes = ul->nodes_head;
while (nodes) {
// skip arbiters
if (nodes->valor == 0) goto next;
if (nodes->valor > best_valor) {
best_node = nodes;
best_valor = nodes->valor;
@@ -353,11 +428,12 @@ struct uwsgi_legion_node *uwsgi_legion_get_lord(struct uwsgi_legion *ul) {
memcpy(best_uuid, nodes->uuid, 36);
}
}
next:
nodes = nodes->next;
}
// first round ?
if (ul->lord_valor == 0) {
// first round ? (skip first round if arbiter)
if (ul->valor > 0 && ul->lord_valor == 0) {
ul->changed = 1;
}
else if (best_valor != ul->lord_valor) {
@@ -521,8 +597,19 @@ static void *legion_loop(void *foobar) {
node->scroll_len = legion_msg.scroll_len;
memcpy(node->scroll, legion_msg.scroll, node->scroll_len);
}
// we are still locked (and safe), let's rebuild the scrolls list
legion_rebuild_scrolls(ul);
uwsgi_rwunlock(ul->lock);
uwsgi_log("[uwsgi-legion] node: %.*s valor: %llu uuid: %.*s joined Legion %s\n", node->name_len, node->name, node->valor, 36, node->uuid, ul->legion);
uwsgi_log("[uwsgi-legion] %s: %.*s valor: %llu uuid: %.*s joined Legion %s\n", node->valor > 0 ? "node" : "arbiter", node->name_len, node->name, node->valor, 36, node->uuid, ul->legion);
// trigger node_joined hooks
struct uwsgi_string_list *usl = ul->node_joined_hooks;
while (usl) {
int ret = uwsgi_legion_action_call("node_joined", ul, usl);
if (ret) {
uwsgi_log("[uwsgi-legion] ERROR, node_joined hook returned: %d\n", ret);
}
usl = usl->next;
}
}
node->last_seen = uwsgi_now();
@@ -710,6 +797,21 @@ err:
return -1;
}
void uwsgi_opt_legion_mcast(char *opt, char *value, void *foobar) {
uwsgi_opt_legion(opt, value, foobar);
char *legion = uwsgi_str(value);
char *space = strchr(legion, ' ');
// over engineering
if (!space) exit(1);
*space = 0;
struct uwsgi_legion *ul = uwsgi_legion_get_by_name(legion);
if (!ul) {
uwsgi_log("unknown legion: %s\n", legion);
exit(1);
}
uwsgi_legion_register_node(ul, uwsgi_str(ul->addr));
}
void uwsgi_opt_legion_node(char *opt, char *value, void *foobar) {
char *legion = uwsgi_str(value);
@@ -727,15 +829,20 @@ void uwsgi_opt_legion_node(char *opt, char *value, void *foobar) {
exit(1);
}
struct uwsgi_string_list *usl = uwsgi_string_new_list(&ul->nodes, space + 1);
char *port = strchr(usl->value, ':');
uwsgi_legion_register_node(ul, space + 1);
}
void uwsgi_legion_register_node(struct uwsgi_legion *ul, char *addr) {
struct uwsgi_string_list *usl = uwsgi_string_new_list(&ul->nodes, addr);
char *port = strchr(addr, ':');
if (!port) {
uwsgi_log("[uwsgi-legion] invalid udp address: %s\n", usl->value);
uwsgi_log("[uwsgi-legion] invalid udp address: %s\n", addr);
exit(1);
}
// no need to zero the memory, socket_to_in_addr will do that
struct sockaddr_in *sin = uwsgi_malloc(sizeof(struct sockaddr_in));
usl->custom = socket_to_in_addr(usl->value, port, 0, sin);
usl->custom = socket_to_in_addr(addr, port, 0, sin);
usl->custom_ptr = sin;
}
@@ -787,51 +894,76 @@ void uwsgi_opt_legion_scroll(char *opt, char *value, void *foobar) {
void uwsgi_opt_legion_hook(char *opt, char *value, void *foobar) {
char *event = strchr(opt, '-');
if (!event) {
uwsgi_log("[uwsgi-legion] invalid option name (%s), this should not happen (possible bug)\n", opt);
exit(1);
}
char *legion = uwsgi_str(value);
char *space = strchr(legion, ' ');
if (!space) {
uwsgi_log("invalid %s syntax, must be <legion> <action>\n", opt);
uwsgi_log("[uwsgi-legion] invalid %s syntax, must be <legion> <action>\n", opt);
exit(1);
}
*space = 0;
struct uwsgi_legion *ul = uwsgi_legion_get_by_name(legion);
if (!ul) {
uwsgi_log("unknown legion: %s\n", legion);
uwsgi_log("[uwsgi-legion] unknown legion: %s\n", legion);
exit(1);
}
uwsgi_legion_register_hook(ul, event + 1, space + 1);
}
void uwsgi_legion_register_hook(struct uwsgi_legion *ul, char *event, char *action) {
struct uwsgi_string_list *usl = NULL;
if (!strcmp(opt, "legion-lord")) {
usl = uwsgi_string_new_list(&ul->lord_hooks, space + 1);
if (!strcmp(event, "lord")) {
usl = uwsgi_string_new_list(&ul->lord_hooks, action);
}
else if (!strcmp(opt, "legion-unlord")) {
usl = uwsgi_string_new_list(&ul->unlord_hooks, space + 1);
else if (!strcmp(event, "unlord")) {
usl = uwsgi_string_new_list(&ul->unlord_hooks, action);
}
else if (!strcmp(opt, "legion-setup")) {
usl = uwsgi_string_new_list(&ul->setup_hooks, space + 1);
else if (!strcmp(event, "setup")) {
usl = uwsgi_string_new_list(&ul->setup_hooks, action);
}
else if (!strcmp(opt, "legion-death")) {
usl = uwsgi_string_new_list(&ul->death_hooks, space + 1);
else if (!strcmp(event, "death")) {
usl = uwsgi_string_new_list(&ul->death_hooks, action);
}
else if (!strcmp(event, "join")) {
usl = uwsgi_string_new_list(&ul->join_hooks, action);
}
else if (!strcmp(event, "node-joined")) {
usl = uwsgi_string_new_list(&ul->node_joined_hooks, action);
}
else if (!strcmp(event, "node-left")) {
usl = uwsgi_string_new_list(&ul->node_left_hooks, action);
}
else {
uwsgi_log("[uwsgi-legion] invalid event: %s\n", event);
exit(1);
}
if (!usl)
return;
char *port = strchr(usl->value, ':');
if (!port) {
uwsgi_log("[uwsgi-legion] invalid %s action: %s\n", opt, usl->value);
char *hook = strchr(action, ':');
if (!hook) {
uwsgi_log("[uwsgi-legion] invalid %s action: %s\n", event, action);
exit(1);
}
// pointer to action plugin
usl->custom_ptr = uwsgi_concat2n(usl->value, port - usl->value, "", 0);
usl->custom_ptr = uwsgi_concat2n(action, hook - action, "", 0);;
// add that to check the plugin value
usl->custom = port - usl->value + 1;
}
usl->custom = hook - action + 1;
}
void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
@@ -869,6 +1001,10 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
*colon = 0;
char *secret = colon + 1;
uwsgi_legion_register(legion, addr, valor, algo_secret, secret);
}
struct uwsgi_legion *uwsgi_legion_register(char *legion, char *addr, char *valor, char *algo, char *secret) {
char *iv = strchr(secret, ' ');
if (iv) {
*iv = 0;
@@ -882,9 +1018,9 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
EVP_CIPHER_CTX *ctx = uwsgi_malloc(sizeof(EVP_CIPHER_CTX));
EVP_CIPHER_CTX_init(ctx);
const EVP_CIPHER *cipher = EVP_get_cipherbyname(algo_secret);
const EVP_CIPHER *cipher = EVP_get_cipherbyname(algo);
if (!cipher) {
uwsgi_log("[uwsgi-legion] unable to find algorithm/cipher %s\n", algo_secret);
uwsgi_log("[uwsgi-legion] unable to find algorithm/cipher %s\n", algo);
exit(1);
}
@@ -937,10 +1073,18 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
uwsgi.legion_scroll_max_size = 4096;
}
if (!uwsgi.legion_scroll_list_max_size) {
uwsgi.legion_scroll_list_max_size = 32768;
}
ul->lord_scroll_size = uwsgi.legion_scroll_max_size;
ul->lord_scroll = uwsgi_calloc_shared(ul->lord_scroll_size);
ul->scrolls_max_size = uwsgi.legion_scroll_list_max_size;
ul->scrolls = uwsgi_calloc_shared(ul->scrolls_max_size);
uwsgi_legion_add(ul);
return ul;
}
struct uwsgi_legion_action *uwsgi_legion_action_get(char *name) {
@@ -1020,3 +1164,15 @@ char *uwsgi_legion_lord_scroll(char *name, uint16_t *rlen) {
uwsgi_rwunlock(legion->lock);
return buf;
}
char *uwsgi_legion_scrolls(char *name, uint64_t *rlen) {
char *buf = NULL;
struct uwsgi_legion *legion = uwsgi_legion_get_by_name(name);
if (!legion) return NULL;
uwsgi_rlock(legion->lock);
buf = uwsgi_malloc(legion->scrolls_len);
memcpy(buf, legion->scrolls, legion->scrolls_len);
*rlen = legion->scrolls_len;
uwsgi_rwunlock(legion->lock);
return buf;
}
+54 -5
View File
@@ -401,6 +401,60 @@ void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_unlock_fast(uli);
}
#elif defined(UWSGI_LOCK_USE_WINDOWS_MUTEX)
#define UWSGI_LOCK_ENGINE_NAME "windows mutexes"
#define UWSGI_LOCK_SIZE sizeof(HANDLE)
#define UWSGI_RWLOCK_SIZE sizeof(HANDLE)
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
struct _SECURITY_ATTRIBUTES sa;
memset(&sa, 0, sizeof(struct _SECURITY_ATTRIBUTES));
sa.bInheritHandle = 1;
uli->lock_ptr = CreateMutex(&sa, FALSE, NULL);
return uli;
}
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
WaitForSingleObject(uli->lock_ptr, INFINITE);
uli->pid = uwsgi.mypid;
}
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
ReleaseMutex(uli->lock_ptr);
uli->pid = 0;
}
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
if (WaitForSingleObject(uli->lock_ptr, 0) == WAIT_TIMEOUT) {
return 0;
}
return uli->pid;
}
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
return uwsgi_lock_fast_init(id);
}
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_lock_fast(uli);
}
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_lock_fast(uli);
}
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) {
return uwsgi_lock_fast_check(uli);
}
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_unlock_fast(uli);
}
#else
#define uwsgi_lock_fast_init uwsgi_lock_ipcsem_init
@@ -420,8 +474,6 @@ void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
#define UWSGI_LOCK_ENGINE_NAME "ipcsem"
#define UWSGI_IPCSEM_ATEXIT 1
#endif
struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
@@ -625,9 +677,6 @@ ready:
// timer table lock
uwsgi.timer_table_lock = uwsgi_lock_init("timer");
// probe table lock
uwsgi.probe_table_lock = uwsgi_lock_init("probe");
// rb_timer table lock
uwsgi.rb_timer_table_lock = uwsgi_lock_init("rbtimer");
+33 -12
View File
@@ -1,9 +1,9 @@
#define _NO_UWSGI_RB
#include "uwsgi.h"
#ifndef __DragonFly__
#include <uwsgi.h>
#endif
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
#include <kvm.h>
#include <sys/user.h>
#include <kvm.h>
#elif defined(__sun__)
/* Terrible Hack !!! */
#ifndef _LP64
@@ -17,6 +17,10 @@
#include <sys/sysctl.h>
#endif
#ifdef __DragonFly__
#include <uwsgi.h>
#endif
extern struct uwsgi_server uwsgi;
//use this instead of fprintf to avoid buffering mess with udp logging
@@ -314,7 +318,7 @@ static struct uwsgi_logger *setup_choosen_logger(struct uwsgi_string_list *usl)
int is_id = 1;
int i;
for (i = 0; i < (space - name); i++) {
if (!isalnum(name[i])) {
if (!isalnum((int)name[i])) {
is_id = 0;
break;
}
@@ -638,12 +642,8 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
}
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
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);
logvec[logvecpos].iov_base = mempkt;
logvec[logvecpos].iov_len = rlen;
logvecpos++;
@@ -673,7 +673,11 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
void get_memusage(uint64_t * rss, uint64_t * vsz) {
#ifdef UNBIT
*vsz = syscall(356);
uint64_t ret[2];
ret[0] = 0; ret[1] = 0;
syscall(358, ret);
*vsz = ret[0];
*rss = ret[1] * uwsgi.page_size;
#elif defined(__linux__)
FILE *procfile;
int i;
@@ -686,6 +690,18 @@ void get_memusage(uint64_t * rss, uint64_t * vsz) {
fclose(procfile);
}
*rss = *rss * uwsgi.page_size;
#elif defined(__CYGWIN__)
// same as Linux but rss is not in pages...
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 %llu %lld", (unsigned long long *) vsz, (unsigned long long *) rss);
if (i != 2) {
uwsgi_log("warning: invalid record in /proc/self/stat\n");
}
fclose(procfile);
}
#elif defined (__sun__)
psinfo_t info;
int procfd;
@@ -725,8 +741,13 @@ void get_memusage(uint64_t * rss, uint64_t * vsz) {
struct kinfo_proc *kproc;
kproc = kvm_getprocs(kv, KERN_PROC_PID, uwsgi.mypid, &cnt);
if (kproc && cnt > 0) {
#if defined(__FreeBSD__)
*vsz = kproc->ki_size;
*rss = kproc->ki_rssize * uwsgi.page_size;
#elif defined(__DragonFly__)
*vsz = kproc->kp_vm_map_size;
*rss = kproc->kp_vm_rssize * uwsgi.page_size;
#endif
}
#elif defined(UWSGI_NEW_OPENBSD)
struct kinfo_proc *kproc;
+19 -35
View File
@@ -638,22 +638,6 @@ int master_loop(char **argv, char **environ) {
uwsgi_manage_command_cron(uwsgi_now());
}
// check for probes
if (ushared->probes_cnt > 0) {
uwsgi_lock(uwsgi.probe_table_lock);
for (i = 0; i < ushared->probes_cnt; i++) {
if (interesting_fd == -1) {
// increment cycles
ushared->probes[i].cycles++;
}
if (ushared->probes[i].func(interesting_fd, &ushared->probes[i])) {
uwsgi_route_signal(ushared->probes[i].sig);
}
}
uwsgi_unlock(uwsgi.probe_table_lock);
}
// some event returned
if (rlen > 0) {
// if the following function returns -1, a new worker has just spawned
@@ -798,8 +782,8 @@ int master_loop(char **argv, char **environ) {
*/
uwsgi.mywid = find_worker_id(diedpid);
if (uwsgi.mywid <= 0) {
int thewid = find_worker_id(diedpid);
if (thewid <= 0) {
// check spooler, mules, gateways and daemons
struct uwsgi_spooler *uspool = uwsgi.spoolers;
while (uspool) {
@@ -842,50 +826,50 @@ next:
// ok a worker died...
uwsgi.workers[uwsgi.mywid].pid = 0;
uwsgi.workers[thewid].pid = 0;
// only to be safe :P
uwsgi.workers[uwsgi.mywid].harakiri = 0;
uwsgi.workers[thewid].harakiri = 0;
// ok, if we are reloading or dying, just continue the master loop
// as soon as all of the workers have pid == 0, the action (exit, or reload) is triggered
if (uwsgi_instance_is_reloading || uwsgi_instance_is_dying) {
uwsgi_log("worker %d buried after %d seconds\n", uwsgi.mywid, (int) (uwsgi_now()-uwsgi.workers[uwsgi.mywid].cursed_at));
uwsgi.workers[uwsgi.mywid].cursed_at = 0;
uwsgi_log("worker %d buried after %d seconds\n", thewid, (int) (uwsgi_now()-uwsgi.workers[thewid].cursed_at));
uwsgi.workers[thewid].cursed_at = 0;
continue;
}
// if we are stopping workers, just end here
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_FAILED_APP_CODE) {
uwsgi_log("OOPS ! failed loading app in worker %d (pid %d) :( trying again...\n", uwsgi.mywid, (int) diedpid);
uwsgi_log("OOPS ! failed loading app in worker %d (pid %d) :( trying again...\n", thewid, (int) diedpid);
}
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_DE_HIJACKED_CODE) {
uwsgi_log("...restoring worker %d (pid: %d)...\n", uwsgi.mywid, (int) diedpid);
uwsgi_log("...restoring worker %d (pid: %d)...\n", thewid, (int) diedpid);
}
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_EXCEPTION_CODE) {
uwsgi_log("... monitored exception detected, respawning worker %d (pid: %d)...\n", uwsgi.mywid, (int) diedpid);
uwsgi_log("... monitored exception detected, respawning worker %d (pid: %d)...\n", thewid, (int) diedpid);
}
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_QUIET_CODE) {
// noop
}
else if (uwsgi.workers[uwsgi.mywid].manage_next_request) {
else if (uwsgi.workers[thewid].manage_next_request) {
if (WIFSIGNALED(waitpid_status)) {
uwsgi_log("DAMN ! worker %d (pid: %d) died, killed by signal %d :( trying respawn ...\n", uwsgi.mywid, (int) diedpid, (int) WTERMSIG(waitpid_status));
uwsgi_log("DAMN ! worker %d (pid: %d) died, killed by signal %d :( trying respawn ...\n", thewid, (int) diedpid, (int) WTERMSIG(waitpid_status));
}
else {
uwsgi_log("DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", uwsgi.mywid, (int) diedpid);
uwsgi_log("DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", thewid, (int) diedpid);
}
}
else if (uwsgi.workers[uwsgi.mywid].cursed_at > 0) {
uwsgi_log("worker %d killed successfully (pid: %d)\n", uwsgi.mywid, (int) diedpid);
else if (uwsgi.workers[thewid].cursed_at > 0) {
uwsgi_log("worker %d killed successfully (pid: %d)\n", thewid, (int) diedpid);
}
// manage_next_request is zero, but killed by signal...
else if (WIFSIGNALED(waitpid_status)) {
uwsgi_log("DAMN ! worker %d (pid: %d) MISTERIOUSLY killed by signal %d :( trying respawn ...\n", uwsgi.mywid, (int) diedpid, (int) WTERMSIG(waitpid_status));
uwsgi_log("DAMN ! worker %d (pid: %d) MISTERIOUSLY killed by signal %d :( trying respawn ...\n", thewid, (int) diedpid, (int) WTERMSIG(waitpid_status));
}
if (uwsgi.workers[uwsgi.mywid].cheaped == 1) {
uwsgi_log("uWSGI worker %d cheaped.\n", uwsgi.mywid);
if (uwsgi.workers[thewid].cheaped == 1) {
uwsgi_log("uWSGI worker %d cheaped.\n", thewid);
continue;
}
@@ -909,12 +893,12 @@ next:
uwsgi.respawn_delta = last_respawn.tv_sec;
// are we chain reloading it ?
if (uwsgi.status.chain_reloading == uwsgi.mywid) {
if (uwsgi.status.chain_reloading == thewid) {
uwsgi.status.chain_reloading++;
}
// respawn the worker (if needed)
if (uwsgi_respawn_worker(uwsgi.mywid))
if (uwsgi_respawn_worker(thewid))
return 0;
// end of the loop
+72 -177
View File
@@ -351,6 +351,9 @@ void uwsgi_reload(char **argv) {
/* check fd table (a module can obviosly open some fd on initialization...) */
uwsgi_log("closing all non-uwsgi socket fds > 2 (max_fd = %d)...\n", (int) uwsgi.max_fd);
for (i = 3; i < (int) uwsgi.max_fd; i++) {
if (uwsgi_fd_is_safe(i)) continue;
int found = 0;
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
@@ -413,9 +416,13 @@ void uwsgi_reload(char **argv) {
#endif
}
#ifdef UWSGI_AS_SHARED_LIBRARY
return;
#else
#ifndef UWSGI_IPCSEM_ATEXIT
// free ipc semaphores if in use
if (uwsgi.lock_engine && !strcmp(uwsgi.lock_engine, "ipcsem")) {
uwsgi_ipcsem_clear();
}
#endif
uwsgi_log("running %s\n", uwsgi.binary_path);
uwsgi_flush_logs();
argv[0] = uwsgi.binary_path;
@@ -436,7 +443,6 @@ void uwsgi_reload(char **argv) {
uwsgi_error("execvp()");
// never here
exit(1);
#endif
}
@@ -634,178 +640,6 @@ int uwsgi_respawn_worker(int wid) {
return 0;
}
void uwsgi_manage_signal_cron(time_t now) {
struct tm *uwsgi_cron_delta;
int i;
uwsgi_cron_delta = localtime(&now);
if (uwsgi_cron_delta) {
// fix month
uwsgi_cron_delta->tm_mon++;
uwsgi_lock(uwsgi.cron_table_lock);
for (i = 0; i < ushared->cron_cnt; i++) {
struct uwsgi_cron *ucron = &ushared->cron[i];
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
uc_minute = ucron->minute;
uc_hour = ucron->hour;
uc_day = ucron->day;
uc_month = ucron->month;
uc_week = ucron->week;
// negative values as interval -1 = * , -5 = */5
if (ucron->minute < 0) {
if ((uwsgi_cron_delta->tm_min % abs(ucron->minute)) == 0) {
uc_minute = uwsgi_cron_delta->tm_min;
}
}
if (ucron->hour < 0) {
if ((uwsgi_cron_delta->tm_hour % abs(ucron->hour)) == 0) {
uc_hour = uwsgi_cron_delta->tm_hour;
}
}
if (ucron->month < 0) {
if ((uwsgi_cron_delta->tm_mon % abs(ucron->month)) == 0) {
uc_month = uwsgi_cron_delta->tm_mon;
}
}
if (ucron->day < 0) {
if ((uwsgi_cron_delta->tm_mday % abs(ucron->day)) == 0) {
uc_day = uwsgi_cron_delta->tm_mday;
}
}
if (ucron->week < 0) {
if ((uwsgi_cron_delta->tm_wday % abs(ucron->week)) == 0) {
uc_week = uwsgi_cron_delta->tm_wday;
}
}
int run_task = 0;
// mday and wday are ORed
if (ucron->day >= 0 && ucron->week >= 0) {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
run_task = 1;
}
}
else {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
run_task = 1;
}
}
if (run_task == 1) {
// date match, signal it ?
if (now - ucron->last_job > 60) {
uwsgi_route_signal(ucron->sig);
ucron->last_job = now;
}
}
}
uwsgi_unlock(uwsgi.cron_table_lock);
}
else {
uwsgi_error("localtime()");
}
}
void uwsgi_manage_command_cron(time_t now) {
struct tm *uwsgi_cron_delta;
struct uwsgi_cron *current_cron = uwsgi.crons;
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
uwsgi_cron_delta = localtime(&now);
if (!uwsgi_cron_delta) {
uwsgi_error("localtime()");
return;
}
// fix month
uwsgi_cron_delta->tm_mon++;
while (current_cron) {
uc_minute = current_cron->minute;
uc_hour = current_cron->hour;
uc_day = current_cron->day;
uc_month = current_cron->month;
uc_week = current_cron->week;
// negative values as interval -1 = * , -5 = */5
if (current_cron->minute < 0) {
if ((uwsgi_cron_delta->tm_min % abs(current_cron->minute)) == 0) {
uc_minute = uwsgi_cron_delta->tm_min;
}
}
if (current_cron->hour < 0) {
if ((uwsgi_cron_delta->tm_hour % abs(current_cron->hour)) == 0) {
uc_hour = uwsgi_cron_delta->tm_hour;
}
}
if (current_cron->month < 0) {
if ((uwsgi_cron_delta->tm_mon % abs(current_cron->month)) == 0) {
uc_month = uwsgi_cron_delta->tm_mon;
}
}
if (current_cron->day < 0) {
if ((uwsgi_cron_delta->tm_mday % abs(current_cron->day)) == 0) {
uc_day = uwsgi_cron_delta->tm_mday;
}
}
if (current_cron->week < 0) {
if ((uwsgi_cron_delta->tm_wday % abs(current_cron->week)) == 0) {
uc_week = uwsgi_cron_delta->tm_wday;
}
}
int run_task = 0;
// mday and wday are ORed
if (current_cron->day >= 0 && current_cron->week >= 0) {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
run_task = 1;
}
}
else {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
run_task = 1;
}
}
if (run_task == 1) {
// date match, run command ?
if (now - current_cron->last_job > 60) {
//call command
if (current_cron->command) {
if (uwsgi_run_command(current_cron->command, NULL, -1) >= 0) {
uwsgi_log_verbose("[uWSGI-cron] running %s\n", current_cron->command);
}
}
current_cron->last_job = now;
}
}
current_cron = current_cron->next;
}
}
struct uwsgi_stats *uwsgi_master_generate_stats() {
int i;
@@ -944,7 +778,10 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
if (uwsgi_stats_keylong_comma(us, "miss", (unsigned long long) uc->miss))
goto end;
if (uwsgi_stats_keylong(us, "full", (unsigned long long) uc->full))
if (uwsgi_stats_keylong_comma(us, "full", (unsigned long long) uc->full))
goto end;
if (uwsgi_stats_keylong(us, "last_modified_at", (unsigned long long) uc->last_modified_at))
goto end;
if (uwsgi_stats_object_close(us))
@@ -957,6 +794,9 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
uc = uc->next;
}
if (uwsgi_stats_list_close(us))
goto end;
if (uwsgi_stats_comma(us))
goto end;
}
@@ -1486,3 +1326,58 @@ void uwsgi_master_fix_request_counters() {
uwsgi.workers[0].requests = total_counter;
}
int uwsgi_cron_task_needs_execution(struct tm *uwsgi_cron_delta, int minute, int hour, int day, int month, int week) {
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
uc_minute = minute;
uc_hour = hour;
uc_day = day;
uc_month = month;
uc_week = week;
// negative values as interval -1 = * , -5 = */5
if (minute < 0) {
if ((uwsgi_cron_delta->tm_min % abs(minute)) == 0) {
uc_minute = uwsgi_cron_delta->tm_min;
}
}
if (hour < 0) {
if ((uwsgi_cron_delta->tm_hour % abs(hour)) == 0) {
uc_hour = uwsgi_cron_delta->tm_hour;
}
}
if (month < 0) {
if ((uwsgi_cron_delta->tm_mon % abs(month)) == 0) {
uc_month = uwsgi_cron_delta->tm_mon;
}
}
if (day < 0) {
if ((uwsgi_cron_delta->tm_mday % abs(day)) == 0) {
uc_day = uwsgi_cron_delta->tm_mday;
}
}
if (week < 0) {
if ((uwsgi_cron_delta->tm_wday % abs(week)) == 0) {
uc_week = uwsgi_cron_delta->tm_wday;
}
}
int run_task = 0;
// mday and wday are ORed
if (day >= 0 && week >= 0) {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
run_task = 1;
}
}
else {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
run_task = 1;
}
}
return run_task;
}
+138
View File
@@ -0,0 +1,138 @@
/*
uWSGI metrics subsystem
a metric is a node in a tree reachable via a numeric id (OID, in SNMP way) or a simple string:
uwsgi.worker.1.requests
uwsgi.custom.foo.bar
the oid representation:
1.3.6.1.4.1.35156.17 = iso.org.dod.internet.private.enterprise.unbit.uwsgi
1.3.6.1.4.1.35156.17.3.1.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.worker.1.requests
1.3.6.1.4.1.35156.17.3.1.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.worker.1.requests
1.3.6.1.4.1.35156.17.3.1.2.1.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.worker.1.core.1.requests
1.3.6.1.4.1.35156.17.4.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.system.load_avg
...
each metric is a collected value with a specific frequency (a frequency of zero means the value is re-computed every time)
metrics are meant for numeric values signed 64 bit, but they can be exposed as:
gauge
counter
absolute
both 32 and 64bit, both signed and unsigned
metrics are managed by a dedicated thread (in the master) holding a linked list of all the items. For few metrics it is a good (read: simple) approach,
but you can cache lookups in a uWSGI cache for really big list.
struct uwsgi_metric *um = uwsgi_register_metric("worker.1.requests", "3.1.1", UWSGI_METRIC_COUNTER, UWSGI_METRIC_PTR, &uwsgi.workers[1].requests, 0, NULL);
prototype: struct uwsgi_metric *uwsgi_register_metric(char *name, char *oid, uint8_t value_type, uint8_t collect_way, void *ptr, uint32_t freq, void *custom);
value_type = UWSGI_METRIC_COUNTER/UWSGI_METRIC_GAUGE/UWSGI_METRIC_ABSOLUTE
collect_way = UWSGI_METRIC_PTR -> get from a pointer / UWSGI_METRIC_FUNC -> get from a func with the prototype int64_t func(struct uwsgi_metric *); / UWSGI_METRIC_FILE -> get the value from a file, ptr is the filename
when freq is zero the value is recomputed whenever requested, otherwise the metrics thread compute it every time the frequency is elapsed and caches it
For some metric (or all ?) you may want to hold a value even after a server reload. For such a reason you can specify a directory on wich the server (on startup/restart) will look for
a file named like the metric and will read the initial value from it. It may look an old-fashioned and quite inefficient way, but it is the most versatile for a sysadmin (allowing him/her
to even modify the values manually)
When registering a metric with the same name of an already registered one, the new one will overwrite the previous one. This allows plugins writer to override default behaviours
Applications are allowed to update metrics (but they cannot register new ones), with simple api funcs:
uwsgi.metric_set("worker.1.requests", N)
uwsgi.metric_inc("worker.1.requests", N=1)
uwsgi.metric_dec("worker.1.requests", N=1)
uwsgi.metric_mul("worker.1.requests", N=1)
uwsgi.metric_div("worker.1.requests", N=1)
and obviously they can get values:
uwsgi.metric_get("worker.1.requests", no_cache|force=False)
if the second parameter is True, the value is recomputed (but if it is a metric with a cache, the cache value will not be updated accordingly, this is the job of the metric thread)
Updating metrics from your app MUST BE ATOMIC, for such a reason a uWSGI rwlock is initialized on startup and used for each operation (simple reading from a metric does not require locking)
Metrics can be updated from the internal routing subsystem too:
route-if = equal:${REQUEST_URI};/foobar metricinc:foobar.test 2
and can be accessed as ${metric[foobar.test]}
The stats server exports the metrics list in the "metrics" attribute (obviously some info could be redundant)
*/
struct uwsgi_metric {
char *name;
char *oid;
// pre-computed snmp representation
char *asn;
size_t asn_size;
// ABSOLUTE/COUNTER/GAUGE
uint8_t type;
// MANUAL/PTR/FUNC/FILE
uint8_t collect_way
// this could be taken from a file storage and must laways be added to value when reporting (default 0)
int64_t initial_value;
// the value of the metric (point to a shared memory area)
*int64_t value;
// a custom blob you can attach to a metric
void *custom;
// the collection frequency
uint32_t freq;
time_t last_update;
// run this function to collect the value
int64_t (*collector)(struct uwsgi_metric *);
// take the value from this pointer to a 64bit value
int64_t *ptr;
// get the initial value from this file, and store each update in it
char *filename;
struct uwsgi_metric *next;
};
struct uwsgi_metric *uwsgi_register_metric(char *name, char *oid, uint8_t value_type, uint8_t collect_way, void *ptr, uint32_t freq, void *custom) {
struct uwsgi_metric *old_metric=NULL,*metric=uwsgi.metric;
while(metric) {
metric = metric->next;
}
}
void uwsgi_metric_loop() {
// every second scan the whole metrics tree
time_t now = uwsgi_now();
}
int64_t uwsgi_metric_get(char *name, char *oid) {
struct uwsgi_metric *um = NULL;
if (name) {
um = uwsgi_metric_find_by_name(name);
}
else if (oid) {
um = uwsgi_metric_find_by_oid(oid);
}
if (!um) return 0;
//
switch(um->collect_way) {
case UWSGI_METRIC_MANUAL:
return um->initial_value+*um->value;
case UWSGI_METRIC_PTR:
return um->initial_value+*um->ptr;
case UWSGI_METRIC_FUNC:
case UWSGI_METRIC_FILE:
}
}
+6 -2
View File
@@ -184,6 +184,7 @@ void uwsgi_mule_handler() {
if (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket || farm_has_signaled(interesting_fd)) {
len = read(interesting_fd, &uwsgi_signal, 1);
if (len <= 0) {
if (len < 0 && (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) continue;
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
end_me(0);
}
@@ -197,7 +198,9 @@ void uwsgi_mule_handler() {
else if (interesting_fd == uwsgi.mules[uwsgi.muleid - 1].queue_pipe[1] || interesting_fd == uwsgi.shared->mule_queue_pipe[1] || farm_has_msg(interesting_fd)) {
len = read(interesting_fd, message, 65536);
if (len < 0) {
uwsgi_error("read()");
if (errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) {
uwsgi_error("uwsgi_mule_handler/read()");
}
}
else {
int i, found = 0;
@@ -343,6 +346,7 @@ next:
if (interesting_fd > -1) {
len = read(interesting_fd, &uwsgi_signal, 1);
if (len <= 0) {
if (len < 0 && (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) goto clear;
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
end_me(0);
}
@@ -350,7 +354,7 @@ next:
uwsgi_log_verbose("master sent signal %d to mule %d\n", uwsgi_signal, uwsgi.muleid);
#endif
if (uwsgi_signal_handler(uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.mywid);
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.muleid);
}
// set the error condition
len = -1;
+1 -1
View File
@@ -72,7 +72,7 @@ int u_offload_transfer_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offlo
return -1;
}
uor->fd = uwsgi_connect(uor->ubuf->buf, 0, 1);
uor->fd = uwsgi_connect(uor->name, 0, 1);
if (uor->fd < 0) {
uwsgi_error("u_offload_transfer_prepare()/connect()");
return -1;
+130 -6
View File
@@ -2,7 +2,7 @@
extern struct uwsgi_server uwsgi;
// this is line uwsgi_str_num but with security checks
// this is like uwsgi_str_num but with security checks
static size_t get_content_length(char *buf, uint16_t size) {
int i;
size_t val = 0;
@@ -80,7 +80,7 @@ ssize_t send_udp_message(uint8_t modifier1, uint8_t modifier2, char *host, char
ret = sendto(fd, (char *) uh, message_size + 4, 0, (struct sockaddr *) &un_addr, sizeof(un_addr));
}
if (ret < 0) {
uwsgi_error("sendto()");
uwsgi_error("send_udp_message()/sendto()");
}
close(fd);
@@ -303,8 +303,41 @@ static int uwsgi_proto_check_9(struct wsgi_request *wsgi_req, char *key, char *b
return 0;
}
static void uwsgi_parse_http_range(char *buf, uint16_t len, size_t *from, size_t *to) {
*from = 0;
*to = 0;
uint16_t rlen = 0;
uint16_t i;
for(i=0;i<len;i++) {
if (buf[i] == ',') break;
rlen++;
}
// bytes=X-
if (rlen < 8) return;
char *equal = memchr(buf, '=', rlen);
if (!equal) return;
if (equal-buf != 5) return;
if (memcmp(buf, "bytes", 5)) return;
char *range = equal+1;
rlen -= 6;
char *dash = memchr(range, '-', rlen);
if (!dash) return;
*from = uwsgi_str_num(range, dash-range);
*to = uwsgi_str_num(dash+1, rlen - ((dash+1)-range));
if (*to > 0 && *from > *to) {
*from = 0;
*to = 0;
}
}
static int uwsgi_proto_check_10(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
if (uwsgi.honour_range && !uwsgi_proto_key("HTTP_RANGE", 10)) {
uwsgi_parse_http_range(buf, len, &wsgi_req->range_from, &wsgi_req->range_to);
return 0;
}
if (!uwsgi_proto_key("UWSGI_FILE", 10)) {
wsgi_req->file = buf;
wsgi_req->file_len = len;
@@ -312,6 +345,12 @@ static int uwsgi_proto_check_10(struct wsgi_request *wsgi_req, char *key, char *
return 0;
}
if (!uwsgi_proto_key("UWSGI_HOME", 10)) {
wsgi_req->home = buf;
wsgi_req->home_len = len;
return 0;
}
return 0;
}
@@ -354,6 +393,13 @@ static int uwsgi_proto_check_11(struct wsgi_request *wsgi_req, char *key, char *
return 0;
}
if (!uwsgi_proto_key("HTTP_COOKIE", 11)) {
wsgi_req->cookie = buf;
wsgi_req->cookie_len = len;
return 0;
}
if (!uwsgi_proto_key("UWSGI_APPID", 11)) {
wsgi_req->appid = buf;
wsgi_req->appid_len = len;
@@ -409,8 +455,8 @@ static int uwsgi_proto_check_12(struct wsgi_request *wsgi_req, char *key, char *
}
if (!uwsgi_proto_key("UWSGI_PYHOME", 12)) {
wsgi_req->pyhome = buf;
wsgi_req->pyhome_len = len;
wsgi_req->home = buf;
wsgi_req->home_len = len;
return 0;
}
@@ -693,7 +739,7 @@ next:
// check if data are available in the local cache
if (wsgi_req->cache_get_len > 0) {
uint64_t cache_value_size;
char *cache_value = uwsgi_cache_magic_get(wsgi_req->cache_get, wsgi_req->cache_get_len, &cache_value_size, NULL);
char *cache_value = uwsgi_cache_magic_get(wsgi_req->cache_get, wsgi_req->cache_get_len, &cache_value_size, NULL, NULL);
if (cache_value && cache_value_size > 0) {
uwsgi_response_write_body_do(wsgi_req, cache_value, cache_value_size);
free(cache_value);
@@ -704,7 +750,7 @@ next:
if (uwsgi.check_cache && wsgi_req->uri_len && wsgi_req->method_len == 3 && wsgi_req->method[0] == 'G' && wsgi_req->method[1] == 'E' && wsgi_req->method[2] == 'T') {
uint64_t cache_value_size;
char *cache_value = uwsgi_cache_magic_get(wsgi_req->uri, wsgi_req->uri_len, &cache_value_size, NULL);
char *cache_value = uwsgi_cache_magic_get(wsgi_req->uri, wsgi_req->uri_len, &cache_value_size, NULL, NULL);
if (cache_value && cache_value_size > 0) {
uwsgi_response_write_body_do(wsgi_req, cache_value, cache_value_size);
free(cache_value);
@@ -962,8 +1008,77 @@ int uwsgi_hooked_parse_array(char *buffer, size_t len, void (*hook) (uint16_t, c
}
// this functions transform a raw HTTP response to a uWSGI-managed response
int uwsgi_blob_to_response(struct wsgi_request *wsgi_req, char *body, size_t len) {
char *line = body;
size_t line_len = 0;
size_t i;
int status_managed = 0;
for(i=0;i<len;i++) {
if (body[i] == '\n') {
// invalid line
if (line_len < 1) {
return -1;
}
if (line[line_len-1] != '\r') {
return -1;
}
// end of the headers
if (line_len == 1) {
break;
}
if (status_managed) {
char *colon = memchr(line, ':', line_len-1);
if (!colon) return -1;
if (colon[1] != ' ') return -1;
if (uwsgi_response_add_header(wsgi_req, line, colon-line, colon+2, (line_len-1) - ((colon+2)-line))) return -1;
}
else {
char *space = memchr(line, ' ', line_len-1);
if (!space) return -1;
if ((line_len-1) - ((space+1)-line) < 3) return -1;
if (uwsgi_response_prepare_headers(wsgi_req, space+1, (line_len-1) - ((space+1)-line))) return -1;
status_managed = 1;
}
line = NULL;
line_len = 0;
}
else {
if (!line) {
line = body + i;
}
line_len++;
}
}
if ((i+1) < len) {
if (uwsgi_response_write_body_do(wsgi_req, body + (i + 1), len-(i+1))) {
return -1;
}
}
return 0;
}
/*
the following functions need to take in account that POST data could be already available in wsgi_req->buffer (generally when uwsgi protocol is in use)
In such a case, allocate a proto_parser_buf and move data there
*/
char *uwsgi_req_append(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, char *val, uint16_t vallen) {
if (!wsgi_req->proto_parser_buf) {
if (wsgi_req->proto_parser_remains > 0) {
wsgi_req->proto_parser_buf = uwsgi_malloc(wsgi_req->proto_parser_remains);
memcpy(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_remains_buf, wsgi_req->proto_parser_remains);
wsgi_req->proto_parser_remains_buf = wsgi_req->proto_parser_buf;
}
}
if ((wsgi_req->uh->pktsize + (2 + keylen + 2 + vallen)) > uwsgi.buffer_size) {
uwsgi_log("not enough buffer space to add %.*s variable, consider increasing it with the --buffer-size option\n", keylen, key);
return NULL;
@@ -1001,6 +1116,15 @@ char *uwsgi_req_append(struct wsgi_request *wsgi_req, char *key, uint16_t keylen
}
int uwsgi_req_append_path_info_with_index(struct wsgi_request *wsgi_req, char *index, uint16_t index_len) {
if (!wsgi_req->proto_parser_buf) {
if (wsgi_req->proto_parser_remains > 0) {
wsgi_req->proto_parser_buf = uwsgi_malloc(wsgi_req->proto_parser_remains);
memcpy(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_remains_buf, wsgi_req->proto_parser_remains);
wsgi_req->proto_parser_remains_buf = wsgi_req->proto_parser_buf;
}
}
uint8_t need_slash = 0;
if (wsgi_req->path_info_len > 0) {
if (wsgi_req->path_info[wsgi_req->path_info_len-1] != '/') {
+57
View File
@@ -0,0 +1,57 @@
#include <uwsgi.h>
/*
QUERY_STRING management functions (mainly used by the internal routing subsystem)
*/
static char *check_qs(char *qs, uint16_t qs_len, char *key, uint16_t keylen, uint16_t *vallen) {
// search for the equal sign
char *equal = memchr(qs, '=', qs_len);
if (!equal) return NULL;
if (uwsgi_strncmp(key, keylen, qs, equal-qs)) {
return NULL;
}
qs_len -= (equal-qs)+1;
if (qs_len == 0) return NULL;
*vallen = qs_len;
return equal+1;
}
char *uwsgi_get_qs(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
uint16_t i;
char *qs = wsgi_req->query_string;
uint16_t qs_len = 0;
char *ptr = wsgi_req->query_string;
//start splitting by ;
for(i=0;i<wsgi_req->query_string_len;i++) {
if (!qs) {
qs = ptr + i;
}
if (ptr[i] == '&') {
char *value = check_qs(qs, qs_len, key, keylen, vallen);
if (value) {
return value;
}
qs_len = 0;
qs = NULL;
}
else {
qs_len++;
}
}
if (qs_len > 0) {
char *value = check_qs(qs, qs_len, key, keylen, vallen);
if (value) {
return value;
}
}
return NULL;
}
+15 -15
View File
@@ -47,7 +47,7 @@ void uwsgi_request_body_seek(struct wsgi_request *wsgi_req, off_t pos) {
if (uwsgi.post_buffering) {
if (pos < 0) {
if (pos > (off_t) wsgi_req->post_pos) {
if ((off_t) wsgi_req->post_pos - pos < 0) {
wsgi_req->post_pos = 0;
return;
}
@@ -108,64 +108,65 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
}
}
remains = UMIN(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark, wsgi_req->post_cl - wsgi_req->post_pos);
// read from a file
if (wsgi_req->post_file) {
size_t ret = fread(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_readline_size - wsgi_req->post_readline_watermark, 1, wsgi_req->post_file);
size_t ret = fread(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, remains, 1, wsgi_req->post_file);
if (ret == 0) {
uwsgi_error("consume_body_for_readline()/fread()");
return -1;
}
wsgi_req->post_pos += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
wsgi_req->post_readline_watermark += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
wsgi_req->post_pos += remains;
wsgi_req->post_readline_watermark += remains;
return 0;
}
// read from post_buffering memory
if (uwsgi.post_buffering) {
wsgi_req->post_pos += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
memcpy(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_buffering_buf + wsgi_req->post_pos, wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
wsgi_req->post_readline_watermark += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
memcpy(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_buffering_buf + wsgi_req->post_pos, remains);
wsgi_req->post_pos += remains;
wsgi_req->post_readline_watermark += remains;
return 0;
}
// read from socket
ssize_t len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
ssize_t len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , remains);
if (len > 0) {
wsgi_req->post_pos += len;
wsgi_req->post_readline_watermark += len;
return 0;
}
if (len == 0) {
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
uwsgi_read_error(remains);
return -1;
}
if (len < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
goto wait;
}
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
uwsgi_read_error(remains);
return -1;
}
wait:
ret = uwsgi_wait_read_req(wsgi_req);
if (ret > 0) {
len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , remains);
if (len > 0) {
wsgi_req->post_pos += len;
wsgi_req->post_readline_watermark += len;
return 0;
}
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
uwsgi_read_error(remains);
return -1;
}
// 0 means timeout
else if (ret == 0) {
uwsgi_read_timeout(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
uwsgi_read_timeout(remains);
return -1;
}
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
uwsgi_read_error(remains);
return -1;
}
@@ -347,7 +348,6 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
if (wsgi_req->post_file) {
if (fread(wsgi_req->post_read_buf + *rlen, remains, 1, wsgi_req->post_file) != 1) {
*rlen = -1;
uwsgi_log("%llu\n", remains);
uwsgi_error("uwsgi_request_body_read()/fread()");
return NULL;
}
+668 -5
View File
@@ -3,6 +3,43 @@
extern struct uwsgi_server uwsgi;
struct uwsgi_route_var *uwsgi_register_route_var(char *name, char *(*func)(struct wsgi_request *, char *, uint16_t, uint16_t *)) {
struct uwsgi_route_var *old_urv = NULL,*urv = uwsgi.route_vars;
while(urv) {
if (!strcmp(urv->name, name)) {
return urv;
}
old_urv = urv;
urv = urv->next;
}
urv = uwsgi_calloc(sizeof(struct uwsgi_route_var));
urv->name = name;
urv->name_len = strlen(name);
urv->func = func;
if (old_urv) {
old_urv->next = urv;
}
else {
uwsgi.route_vars = urv;
}
return urv;
}
struct uwsgi_route_var *uwsgi_get_route_var(char *name, uint16_t name_len) {
struct uwsgi_route_var *urv = uwsgi.route_vars;
while(urv) {
if (!uwsgi_strncmp(urv->name, urv->name_len, name, name_len)) {
return urv;
}
urv = urv->next;
}
return NULL;
}
struct uwsgi_buffer *uwsgi_routing_translate(struct wsgi_request *wsgi_req, struct uwsgi_route *ur, char *subject, uint16_t subject_len, char *data, size_t data_len) {
char *pass1 = data;
@@ -44,9 +81,32 @@ struct uwsgi_buffer *uwsgi_routing_translate(struct wsgi_request *wsgi_req, stru
case 2:
if (pass1[i] == '}') {
uint16_t vallen = 0;
char *value = uwsgi_get_var(wsgi_req, key, keylen, &vallen);
int need_free = 0;
char *value = NULL;
char *bracket = memchr(key, '[', keylen);
if (bracket && keylen > 0 && key[keylen-1] == ']') {
struct uwsgi_route_var *urv = uwsgi_get_route_var(key, bracket - key);
if (urv) {
need_free = urv->need_free;
value = urv->func(wsgi_req, bracket + 1, keylen - (urv->name_len+2), &vallen);
}
else {
value = uwsgi_get_var(wsgi_req, key, keylen, &vallen);
}
}
else {
value = uwsgi_get_var(wsgi_req, key, keylen, &vallen);
}
if (value) {
if (uwsgi_buffer_append(ub, value, vallen)) goto error;
if (uwsgi_buffer_append(ub, value, vallen)) {
if (need_free) {
free(value);
}
goto error;
}
if (need_free) {
free(value);
}
}
status = 0;
key = NULL;
@@ -97,6 +157,8 @@ int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t
while (routes) {
if (routes->label) goto next;
if (wsgi_req->route_goto > 0 && wsgi_req->route_pc < wsgi_req->route_goto) {
goto next;
}
@@ -108,6 +170,11 @@ int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t
wsgi_req->route_goto = 0;
if (!routes->if_func) {
// could be a "run"
if (!routes->subject) {
n = 0;
goto run;
}
if (!subject) {
char **subject2 = (char **) (((char *) (wsgi_req)) + routes->subject);
uint16_t *subject_len2 = (uint16_t *) (((char *) (wsgi_req)) + routes->subject_len);
@@ -137,6 +204,7 @@ int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t
}
}
run:
if (n >= 0) {
wsgi_req->is_routing = 1;
int ret = routes->func(wsgi_req, routes);
@@ -152,6 +220,10 @@ int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t
if (ret == UWSGI_ROUTE_GOON) {
goon_func = routes->func;
}
if (ret == -1) {
return UWSGI_ROUTE_BREAK;
}
}
next:
subject = orig_subject;
@@ -176,7 +248,7 @@ int uwsgi_apply_routes(struct wsgi_request *wsgi_req) {
return UWSGI_ROUTE_BREAK;
}
// in case ogf static files serving previous rules could be applied
// in case of static files serving previous rules could be applied
if (wsgi_req->routes_applied) {
return UWSGI_ROUTE_CONTINUE;
}
@@ -197,6 +269,8 @@ static void *uwsgi_route_get_condition_func(char *name) {
void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
char *space = NULL;
char *command = NULL;
struct uwsgi_route *old_ur = NULL,*ur = uwsgi.routes;
uint64_t pos = 0;
while(ur) {
@@ -223,7 +297,12 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
char *route = uwsgi_str(value);
char *space = strchr(route, ' ');
if (!strcmp(foobar, "run")) {
command = route;
goto done;
}
space = strchr(route, ' ');
if (!space) {
uwsgi_log("invalid route syntax\n");
exit(1);
@@ -299,7 +378,8 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
}
}
char *command = space + 1;
command = space + 1;
done:
ur->action = uwsgi_str(command);
char *colon = strchr(command, ':');
@@ -405,6 +485,28 @@ static int uwsgi_router_goon(struct uwsgi_route *ur, char *arg) {
return 0;
}
// flush response
static int transform_flush(struct wsgi_request *wsgi_req, struct uwsgi_buffer *ub, struct uwsgi_buffer **foobar, void *data) {
wsgi_req->flush = 1;
return uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
return 0;
}
static int uwsgi_router_flush_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
// if there are no transformations defined, set the flush right now
if (!wsgi_req->transformations) {
wsgi_req->flush = 1;
}
else {
// otherwise push it in the chain
uwsgi_add_transformation(wsgi_req, transform_flush, NULL);
}
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_flush(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_flush_func;
return 0;
}
// log route
static int uwsgi_router_log_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
@@ -585,6 +687,153 @@ static int uwsgi_router_signal(struct uwsgi_route *ur, char *arg) {
return 0;
}
// chdir route
static int uwsgi_router_chdir_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
if (chdir(ub->buf)) {
uwsgi_error("uwsgi_router_chdir_func()/chdir()");
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_chdir(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_chdir_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// setapp route
static int uwsgi_router_setapp_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
char *ptr = uwsgi_req_append(wsgi_req, "UWSGI_APPID", 11, ub->buf, ub->pos);
if (!ptr) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
wsgi_req->appid = ptr;
wsgi_req->appid_len = ub->pos;
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_setapp(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_setapp_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// sethome route
static int uwsgi_router_sethome_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
char *ptr = uwsgi_req_append(wsgi_req, "UWSGI_HOME", 10, ub->buf, ub->pos);
if (!ptr) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
wsgi_req->home = ptr;
wsgi_req->home_len = ub->pos;
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_sethome(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_sethome_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// setfile route
static int uwsgi_router_setfile_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
char *ptr = uwsgi_req_append(wsgi_req, "UWSGI_HOME", 10, ub->buf, ub->pos);
if (!ptr) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
wsgi_req->file = ptr;
wsgi_req->file_len = ub->pos;
wsgi_req->dynamic = 1;
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_setfile(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_setfile_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// setprocname route
static int uwsgi_router_setprocname_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
uwsgi_set_processname(ub->buf);
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_setprocname(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_setprocname_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// alarm route
static int uwsgi_router_alarm_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub_alarm = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub_alarm) return UWSGI_ROUTE_BREAK;
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data2, ur->data2_len);
if (!ub) {
uwsgi_buffer_destroy(ub_alarm);
return UWSGI_ROUTE_BREAK;
}
uwsgi_alarm_trigger(ub_alarm->buf, ub->buf, ub->pos);
uwsgi_buffer_destroy(ub_alarm);
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_alarm(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_alarm_func;
char *space = strchr(arg, ' ');
if (!space) {
return -1;
}
*space = 0;
ur->data = arg;
ur->data_len = strlen(arg);
ur->data2 = space+1;
ur->data2_len = strlen(ur->data2);
return 0;
}
// send route
static int uwsgi_router_send_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
@@ -628,6 +877,269 @@ static int uwsgi_route_condition_isfile(struct wsgi_request *wsgi_req, struct uw
return 0;
}
static int uwsgi_route_condition_regexp(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
if (!semicolon) return 0;
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
if (!ub) return -1;
pcre *pattern;
pcre_extra *pattern_extra;
char *re = uwsgi_concat2n(semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str), "", 0);
if (uwsgi_regexp_build(re, &pattern, &pattern_extra)) {
free(re);
uwsgi_buffer_destroy(ub);
return -1;
}
free(re);
if (uwsgi_regexp_match(pattern, pattern_extra, ub->buf, ub->pos) >= 0) {
uwsgi_buffer_destroy(ub);
pcre_free(pattern);
#ifdef PCRE_STUDY_JIT_COMPILE
pcre_free_study(pattern_extra);
#else
pcre_free(pattern_extra);
#endif
return 1;
}
uwsgi_buffer_destroy(ub);
pcre_free(pattern);
#ifdef PCRE_STUDY_JIT_COMPILE
pcre_free_study(pattern_extra);
#else
pcre_free(pattern_extra);
#endif
return 0;
}
static int uwsgi_route_condition_empty(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, ur->subject_str_len);
if (!ub) return -1;
if (ub->pos == 0) {
uwsgi_buffer_destroy(ub);
return 1;
}
uwsgi_buffer_destroy(ub);
return 0;
}
static int uwsgi_route_condition_equal(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
if (!semicolon) return 0;
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
if (!ub) return -1;
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
if (!ub2) {
uwsgi_buffer_destroy(ub);
return -1;
}
if(!uwsgi_strncmp(ub->buf, ub->pos, ub2->buf, ub2->pos)) {
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 1;
}
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 0;
}
static int uwsgi_route_condition_higher(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
if (!semicolon) return 0;
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
if (!ub) return -1;
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
if (!ub2) {
uwsgi_buffer_destroy(ub);
return -1;
}
long num1 = strtol(ub->buf, NULL, 10);
long num2 = strtol(ub2->buf, NULL, 10);
if(num1 > num2) {
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 1;
}
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 0;
}
static int uwsgi_route_condition_higherequal(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
if (!semicolon) return 0;
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
if (!ub) return -1;
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
if (!ub2) {
uwsgi_buffer_destroy(ub);
return -1;
}
long num1 = strtol(ub->buf, NULL, 10);
long num2 = strtol(ub2->buf, NULL, 10);
if(num1 >= num2) {
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 1;
}
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 0;
}
static int uwsgi_route_condition_lower(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
if (!semicolon) return 0;
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
if (!ub) return -1;
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
if (!ub2) {
uwsgi_buffer_destroy(ub);
return -1;
}
long num1 = strtol(ub->buf, NULL, 10);
long num2 = strtol(ub2->buf, NULL, 10);
if(num1 < num2) {
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 1;
}
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 0;
}
static int uwsgi_route_condition_lowerequal(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
if (!semicolon) return 0;
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
if (!ub) return -1;
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
if (!ub2) {
uwsgi_buffer_destroy(ub);
return -1;
}
long num1 = strtol(ub->buf, NULL, 10);
long num2 = strtol(ub2->buf, NULL, 10);
if(num1 <= num2) {
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 1;
}
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 0;
}
#ifdef UWSGI_SSL
static int uwsgi_route_condition_lord(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, ur->subject_str_len);
if (!ub) return -1;
int ret = uwsgi_legion_i_am_the_lord(ub->buf);
uwsgi_buffer_destroy(ub);
return ret;
}
#endif
static int uwsgi_route_condition_startswith(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
if (!semicolon) return 0;
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
if (!ub) return -1;
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
if (!ub2) {
uwsgi_buffer_destroy(ub);
return -1;
}
if(!uwsgi_starts_with(ub->buf, ub->pos, ub2->buf, ub2->pos)) {
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 1;
}
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 0;
}
static int uwsgi_route_condition_contains(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
if (!semicolon) return 0;
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
if (!ub) return -1;
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
if (!ub2) {
uwsgi_buffer_destroy(ub);
return -1;
}
if(uwsgi_contains_n(ub->buf, ub->pos, ub2->buf, ub2->pos)) {
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 1;
}
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 0;
}
static int uwsgi_route_condition_endswith(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
if (!semicolon) return 0;
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
if (!ub) return -1;
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
if (!ub2) {
uwsgi_buffer_destroy(ub);
return -1;
}
if (ub2->pos < ub->pos) goto zero;
if(!uwsgi_strncmp(ub->buf + (ub->pos - ub2->pos), ub2->pos, ub2->buf, ub2->pos)) {
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 1;
}
zero:
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 0;
}
static int uwsgi_route_condition_isdir(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, ur->subject_str_len);
if (!ub) return -1;
@@ -662,6 +1174,106 @@ static int uwsgi_route_condition_isexec(struct wsgi_request *wsgi_req, struct uw
return 0;
}
static char *uwsgi_route_var_uwsgi(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
char *ret = NULL;
if (!uwsgi_strncmp(key, keylen, "wid", 3)) {
ret = uwsgi_num2str(uwsgi.mywid);
*vallen = strlen(ret);
}
else if (!uwsgi_strncmp(key, keylen, "pid", 3)) {
ret = uwsgi_num2str(uwsgi.mypid);
*vallen = strlen(ret);
}
return ret;
}
static char *uwsgi_route_var_mime(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
char *ret = NULL;
uint16_t var_vallen = 0;
char *var_value = uwsgi_get_var(wsgi_req, key, keylen, &var_vallen);
if (var_value) {
size_t mime_type_len = 0;
char *ret = uwsgi_get_mime_type(key, keylen, &mime_type_len);
if (ret) *vallen = mime_type_len;
}
return ret;
}
static char *uwsgi_route_var_time(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
char *ret = NULL;
if (!uwsgi_strncmp(key, keylen, "unix", 4)) {
ret = uwsgi_num2str(uwsgi_now());
*vallen = strlen(ret);
}
return ret;
}
static char *uwsgi_route_var_base64(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
char *ret = NULL;
uint16_t var_vallen = 0;
char *var_value = uwsgi_get_var(wsgi_req, key, keylen, &var_vallen);
if (var_value) {
size_t b64_len = 0;
ret = uwsgi_base64_encode(var_value, var_vallen, &b64_len);
*vallen = b64_len;
}
return ret;
}
static char *uwsgi_route_var_hex(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
char *ret = NULL;
uint16_t var_vallen = 0;
char *var_value = uwsgi_get_var(wsgi_req, key, keylen, &var_vallen);
if (var_value) {
ret = uwsgi_str_to_hex(var_value, var_vallen);
*vallen = var_vallen*2;
}
return ret;
}
#ifdef UWSGI_MATHEVAL
static char *uwsgi_route_var_math(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
char *ret = NULL;
// avoid crash
if (!wsgi_req->var_cnt) return NULL;
// we make a bit of fun here, we do a copy of the vars buffer (+1 byte for final zero) and zeor-pad all of the strings
char *vars_buf = uwsgi_malloc(wsgi_req->uh->pktsize + keylen + 1);
char **names = uwsgi_malloc(sizeof(char *) * (wsgi_req->var_cnt/2));
double *values = uwsgi_calloc(sizeof(double) * (wsgi_req->var_cnt/2));
int i,j = 0;
char *ptr = vars_buf;
for (i = wsgi_req->var_cnt-1; i > 0; i -= 2) {
memcpy(ptr, wsgi_req->hvec[i-1].iov_base, wsgi_req->hvec[i-1].iov_len);
names[j] = ptr;
ptr += wsgi_req->hvec[i-1].iov_len;
*ptr++=0;
char *num = ptr;
memcpy(ptr, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
ptr += wsgi_req->hvec[i].iov_len;
*ptr++=0;
values[j] = strtod(num, NULL);
j++;
}
char *expr = ptr;
memcpy(ptr, key, keylen); ptr += keylen;
*ptr++=0;
void *e = evaluator_create(expr);
if (!e) goto end;
double n = evaluator_evaluate(e, j, names, values);
evaluator_destroy(e);
ret = uwsgi_num2str((int)n);
*vallen = strlen(ret);
end:
free(vars_buf);
free(names);
free(values);
return ret;
}
#endif
// register embedded routers
void uwsgi_register_embedded_routers() {
@@ -679,12 +1291,60 @@ void uwsgi_register_embedded_routers() {
uwsgi_register_router("signal", uwsgi_router_signal);
uwsgi_register_router("send", uwsgi_router_send);
uwsgi_register_router("send-crnl", uwsgi_router_send_crnl);
uwsgi_register_router("chdir", uwsgi_router_chdir);
uwsgi_register_router("setapp", uwsgi_router_setapp);
uwsgi_register_router("sethome", uwsgi_router_sethome);
uwsgi_register_router("setfile", uwsgi_router_setfile);
uwsgi_register_router("setprocname", uwsgi_router_setprocname);
uwsgi_register_router("alarm", uwsgi_router_alarm);
uwsgi_register_router("flush", uwsgi_router_flush);
uwsgi_register_route_condition("exists", uwsgi_route_condition_exists);
uwsgi_register_route_condition("isfile", uwsgi_route_condition_isfile);
uwsgi_register_route_condition("isdir", uwsgi_route_condition_isdir);
uwsgi_register_route_condition("islink", uwsgi_route_condition_islink);
uwsgi_register_route_condition("isexec", uwsgi_route_condition_isexec);
uwsgi_register_route_condition("equal", uwsgi_route_condition_equal);
uwsgi_register_route_condition("isequal", uwsgi_route_condition_equal);
uwsgi_register_route_condition("eq", uwsgi_route_condition_equal);
uwsgi_register_route_condition("==", uwsgi_route_condition_equal);
uwsgi_register_route_condition("startswith", uwsgi_route_condition_startswith);
uwsgi_register_route_condition("endswith", uwsgi_route_condition_endswith);
uwsgi_register_route_condition("regexp", uwsgi_route_condition_regexp);
uwsgi_register_route_condition("re", uwsgi_route_condition_regexp);
uwsgi_register_route_condition("ishigher", uwsgi_route_condition_higher);
uwsgi_register_route_condition(">", uwsgi_route_condition_higher);
uwsgi_register_route_condition("islower", uwsgi_route_condition_lower);
uwsgi_register_route_condition("<", uwsgi_route_condition_lower);
uwsgi_register_route_condition("ishigherequal", uwsgi_route_condition_higherequal);
uwsgi_register_route_condition(">=", uwsgi_route_condition_higherequal);
uwsgi_register_route_condition("islowerequal", uwsgi_route_condition_lowerequal);
uwsgi_register_route_condition("<=", uwsgi_route_condition_lowerequal);
uwsgi_register_route_condition("contains", uwsgi_route_condition_contains);
uwsgi_register_route_condition("contain", uwsgi_route_condition_contains);
#ifdef UWSGI_SSL
uwsgi_register_route_condition("lord", uwsgi_route_condition_lord);
#endif
uwsgi_register_route_condition("empty", uwsgi_route_condition_empty);
uwsgi_register_route_var("cookie", uwsgi_get_cookie);
uwsgi_register_route_var("qs", uwsgi_get_qs);
uwsgi_register_route_var("mime", uwsgi_route_var_mime);
struct uwsgi_route_var *urv = uwsgi_register_route_var("uwsgi", uwsgi_route_var_uwsgi);
urv->need_free = 1;
urv = uwsgi_register_route_var("time", uwsgi_route_var_time);
urv->need_free = 1;
#ifdef UWSGI_MATHEVAL
urv = uwsgi_register_route_var("math", uwsgi_route_var_math);
urv->need_free = 1;
#endif
urv = uwsgi_register_route_var("base64", uwsgi_route_var_base64);
urv->need_free = 1;
urv = uwsgi_register_route_var("hex", uwsgi_route_var_hex);
urv->need_free = 1;
}
struct uwsgi_router *uwsgi_register_router(char *name, int (*func) (struct uwsgi_route *, char *)) {
@@ -743,6 +1403,9 @@ void uwsgi_routing_dump() {
if (routes->label) {
uwsgi_log("[rule: %llu] label: %s\n", (unsigned long long ) routes->pos, routes->label);
}
else if (!routes->subject_str && !routes->if_func) {
uwsgi_log("[rule: %llu] action: %s\n", (unsigned long long ) routes->pos, routes->action);
}
else {
uwsgi_log("[rule: %llu] subject: %s %s: %s%s action: %s\n", (unsigned long long ) routes->pos, routes->subject_str, routes->if_func ? "func" : "regexp", routes->if_negate ? "!" : "", routes->regexp, routes->action);
}
+5 -5
View File
@@ -1,8 +1,8 @@
#include "uwsgi.h"
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
int uwsgi_register_rpc(char *name, uint8_t modifier1, uint8_t args, void *func) {
int uwsgi_register_rpc(char *name, struct uwsgi_plugin *plugin, uint8_t args, void *func) {
struct uwsgi_rpc *urpc;
int ret = -1;
@@ -30,7 +30,7 @@ int uwsgi_register_rpc(char *name, uint8_t modifier1, uint8_t args, void *func)
uwsgi.shared->rpc_count[uwsgi.mywid]++;
already:
memcpy(urpc->name, name, strlen(name));
urpc->modifier1 = modifier1;
urpc->plugin = plugin;
urpc->args = args;
urpc->func = func;
urpc->shared = uwsgi.mywid == 0 ? 1 : 0;
@@ -77,8 +77,8 @@ uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], cha
}
if (urpc) {
if (uwsgi.p[urpc->modifier1]->rpc) {
ret = uwsgi.p[urpc->modifier1]->rpc(urpc->func, argc, argv, argvs, output);
if (urpc->plugin->rpc) {
ret = urpc->plugin->rpc(urpc->func, argc, argv, argvs, output);
}
}
+13
View File
@@ -106,6 +106,9 @@ void uwsgi_setup_inherited_sockets() {
//now close all the unbound fd
for (j = 3; j < (int) uwsgi.max_fd; j++) {
int useless = 1;
if (uwsgi_fd_is_safe(j)) continue;
if (uwsgi.has_emperor) {
if (j == uwsgi.emperor_fd)
continue;
@@ -123,6 +126,16 @@ void uwsgi_setup_inherited_sockets() {
continue;
}
if (uwsgi.shared->worker_req_log_pipe[0] > -1) {
if (j == uwsgi.shared->worker_req_log_pipe[0])
continue;
}
if (uwsgi.shared->worker_req_log_pipe[1] > -1) {
if (j == uwsgi.shared->worker_req_log_pipe[1])
continue;
}
if (uwsgi.original_log_fd > -1) {
if (j == uwsgi.original_log_fd)
continue;
+4 -140
View File
@@ -137,7 +137,7 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
int i;
for(i=1;i<=uwsgi.numproc;i++) {
int pos = (i * 256);
memcpy(&uwsgi.shared->signal_table[pos], use, sizeof(struct uwsgi_signal_entry) * 256);
memcpy(&uwsgi.shared->signal_table[pos], &uwsgi.shared->signal_table[0], sizeof(struct uwsgi_signal_entry) * 256);
}
}
@@ -177,89 +177,10 @@ int uwsgi_add_file_monitor(uint8_t sig, char *filename) {
}
struct uwsgi_probe *uwsgi_probe_register(struct uwsgi_probe **up, char *name, int (*func) (int, struct uwsgi_signal_probe *)) {
struct uwsgi_probe *uwsgi_up = *up, *old_up;
if (!uwsgi_up) {
*up = uwsgi_malloc(sizeof(struct uwsgi_probe));
uwsgi_up = *up;
}
else {
while (uwsgi_up) {
old_up = uwsgi_up;
uwsgi_up = uwsgi_up->next;
}
uwsgi_up = uwsgi_malloc(sizeof(struct uwsgi_probe));
old_up->next = uwsgi_up;
}
uwsgi_up->name = name;
uwsgi_up->func = func;
uwsgi_up->next = NULL;
uwsgi_log("registered new probe \"%s\" at %p\n", name, uwsgi_up);
return uwsgi_up;
}
int uwsgi_add_probe(uint8_t sig, char *kind, char *args, int timeout, int freq) {
uwsgi_lock(uwsgi.probe_table_lock);
if (ushared->probes_cnt < MAX_PROBES) {
struct uwsgi_probe *up = uwsgi.probes;
while (up) {
if (!strcmp(up->name, kind)) {
break;
}
up = up->next;
}
if (!up) {
uwsgi_log("unable to find probe \"%s\" !!!\n", kind);
uwsgi_unlock(uwsgi.probe_table_lock);
return -1;
}
// fill the probe table
ushared->probes[ushared->probes_cnt].func = up->func;
strncpy(ushared->probes[ushared->probes_cnt].args, args, 1024 - 1);
ushared->probes[ushared->probes_cnt].registered = 0;
ushared->probes[ushared->probes_cnt].sig = sig;
ushared->probes[ushared->probes_cnt].fd = -1;
ushared->probes[ushared->probes_cnt].state = 0;
ushared->probes[ushared->probes_cnt].last_event = 0;
ushared->probes[ushared->probes_cnt].data = NULL;
ushared->probes[ushared->probes_cnt].cycles = 0;
ushared->probes[ushared->probes_cnt].bad = 0;
if (!timeout) {
timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
}
ushared->probes[ushared->probes_cnt].timeout = timeout;
if (!freq) {
freq = 1;
}
ushared->probes[ushared->probes_cnt].freq = freq;
ushared->probes_cnt++;
}
else {
uwsgi_log("you can register max %d probes !!!\n", MAX_PROBES);
uwsgi_unlock(uwsgi.probe_table_lock);
return -1;
}
uwsgi_unlock(uwsgi.probe_table_lock);
return 0;
}
int uwsgi_add_timer(uint8_t sig, int secs) {
if (!uwsgi.master_process) return -1;
uwsgi_lock(uwsgi.timer_table_lock);
if (ushared->timers_cnt < 64) {
@@ -282,63 +203,6 @@ int uwsgi_add_timer(uint8_t sig, int secs) {
}
void uwsgi_opt_add_cron(char *opt, char *value, void *foobar) {
int i;
struct uwsgi_cron *old_uc, *uc = uwsgi.crons;
if (!uc) {
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
uwsgi.crons = uc;
}
else {
old_uc = uc;
while (uc->next) {
uc = uc->next;
old_uc = uc;
}
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
uc = old_uc->next;
}
memset(uc, 0, sizeof(struct uwsgi_cron));
if (sscanf(value, "%d %d %d %d %d %n", &uc->minute, &uc->hour, &uc->day, &uc->month, &uc->week, &i) != 5) {
uwsgi_log("invalid cron syntax\n");
exit(1);
}
uc->command = value + i;
}
int uwsgi_signal_add_cron(uint8_t sig, int minute, int hour, int day, int month, int week) {
if (!uwsgi.master_process)
return -1;
uwsgi_lock(uwsgi.cron_table_lock);
if (ushared->cron_cnt < MAX_CRONS) {
ushared->cron[ushared->cron_cnt].sig = sig;
ushared->cron[ushared->cron_cnt].minute = minute;
ushared->cron[ushared->cron_cnt].hour = hour;
ushared->cron[ushared->cron_cnt].day = day;
ushared->cron[ushared->cron_cnt].month = month;
ushared->cron[ushared->cron_cnt].week = week;
ushared->cron_cnt++;
}
else {
uwsgi_log("you can register max %d cron !!!\n", MAX_CRONS);
uwsgi_unlock(uwsgi.cron_table_lock);
return -1;
}
uwsgi_unlock(uwsgi.cron_table_lock);
return 0;
}
int uwsgi_signal_add_rb_timer(uint8_t sig, int secs, int iterations) {
if (!uwsgi.master_process)
@@ -595,7 +459,7 @@ void uwsgi_receive_signal(int fd, char *name, int id) {
if (ret == 0) {
goto destroy;
}
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) {
uwsgi_error("[uwsgi-signal] read()");
goto destroy;
}
+69 -1
View File
@@ -2,6 +2,23 @@
extern struct uwsgi_server uwsgi;
static int uwsgi_socket_strcmp(char *sock1, char *sock2) {
size_t sock1_len = strlen(sock1);
size_t sock2_len = strlen(sock2);
if (!uwsgi_starts_with(sock1, sock1_len, "0.0.0.0:", 8)) {
sock1 += 7;
sock1_len = strlen(sock1);
}
if (!uwsgi_starts_with(sock2, sock2_len, "0.0.0.0:", 8)) {
sock2 += 7;
sock2_len = strlen(sock2);
}
return uwsgi_strncmp(sock1, sock1_len, sock2, sock2_len);
}
char *uwsgi_getsockname(int fd) {
socklen_t socket_type_len = sizeof(struct sockaddr_un);
@@ -49,6 +66,7 @@ int bind_to_unix_dgram(char *socket_name) {
if (serverfd < 0) {
uwsgi_error("socket()");
uwsgi_nuclear_blast();
return -1;
}
if (unlink(socket_name) != 0 && errno != ENOENT) {
@@ -68,6 +86,7 @@ int bind_to_unix_dgram(char *socket_name) {
#endif
uwsgi_error("bind()");
uwsgi_nuclear_blast();
return -1;
}
return serverfd;
@@ -83,6 +102,7 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
if (strlen(socket_name) > 102) {
uwsgi_log("invalid socket name\n");
uwsgi_nuclear_blast();
return -1;
}
if (socket_name[0] == '@') {
@@ -96,6 +116,7 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
if (uws_addr == NULL) {
uwsgi_error("malloc()");
uwsgi_nuclear_blast();
return -1;
}
memset(uws_addr, 0, sizeof(struct sockaddr_un));
@@ -103,6 +124,7 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
if (serverfd < 0) {
uwsgi_error("socket()");
uwsgi_nuclear_blast();
return -1;
}
if (abstract_socket == 0) {
if (unlink(socket_name) != 0 && errno != ENOENT) {
@@ -114,6 +136,24 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
uwsgi_log("setting abstract socket mode (warning: only Linux supports this)\n");
}
if (uwsgi.so_sndbuf) {
socklen_t sndbuf = (socklen_t) uwsgi.so_sndbuf;
if (setsockopt(serverfd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(socklen_t)) < 0) {
uwsgi_error("SO_SNDBUF setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
}
if (uwsgi.so_rcvbuf) {
socklen_t rcvbuf = (socklen_t) uwsgi.so_rcvbuf;
if (setsockopt(serverfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(socklen_t)) < 0) {
uwsgi_error("SO_RCVBUF setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
}
uws_addr->sun_family = AF_UNIX;
if (socket_name[0] == '@') {
memcpy(uws_addr->sun_path + abstract_socket, socket_name + 1, UMIN(strlen(socket_name + 1), 101));
@@ -140,12 +180,14 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
#endif
uwsgi_error("bind()");
uwsgi_nuclear_blast();
return -1;
}
if (listen(serverfd, listen_queue) != 0) {
uwsgi_error("listen()");
uwsgi_nuclear_blast();
return -1;
}
// chmod unix socket for lazy users
@@ -561,11 +603,31 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
if (serverfd < 0) {
uwsgi_error("socket()");
uwsgi_nuclear_blast();
return -1;
}
if (uwsgi.so_sndbuf) {
socklen_t sndbuf = (socklen_t) uwsgi.so_sndbuf;
if (setsockopt(serverfd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(socklen_t)) < 0) {
uwsgi_error("SO_SNDBUF setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
}
if (uwsgi.so_rcvbuf) {
socklen_t rcvbuf = (socklen_t) uwsgi.so_rcvbuf;
if (setsockopt(serverfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(socklen_t)) < 0) {
uwsgi_error("SO_RCVBUF setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
}
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
uwsgi_error("SO_REUSEADDR setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
#ifdef __linux__
@@ -576,6 +638,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
if (setsockopt(serverfd, SOL_IP, IP_FREEBIND, (const void *) &uwsgi.freebind, sizeof(int)) < 0) {
uwsgi_error("IP_FREEBIND setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
}
#endif
@@ -585,6 +648,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEPORT, (const void *) &uwsgi.reuse_port, sizeof(int)) < 0) {
uwsgi_error("SO_REUSEPORT setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
#else
uwsgi_log("!!! your system does not support SO_REUSEPORT !!!\n");
@@ -611,6 +675,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
if (setsockopt(serverfd, SOL_SOCKET, SO_SNDTIMEO, (const void *) &tv, sizeof(struct timeval)) < 0) {
uwsgi_error("SO_SNDTIMEO setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
}
@@ -645,6 +710,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
}
uwsgi_error("bind()");
uwsgi_nuclear_blast();
return -1;
}
#ifdef __linux__
@@ -652,12 +718,14 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
if (somaxconn > 0 && uwsgi.listen_queue > somaxconn) {
uwsgi_log("Listen queue size is greater than the system max net.core.somaxconn (%li).\n", somaxconn);
uwsgi_nuclear_blast();
return -1;
}
#endif
if (listen(serverfd, listen_queue) != 0) {
uwsgi_error("listen()");
uwsgi_nuclear_blast();
return -1;
}
@@ -1476,7 +1544,7 @@ void uwsgi_setup_shared_sockets() {
for (i = 3; i < (int) uwsgi.max_fd; i++) {
char *sock = uwsgi_getsockname(i);
if (sock) {
if (!strcmp(sock, shared_sock->name)) {
if (!uwsgi_socket_strcmp(sock, shared_sock->name)) {
if (strchr(sock, ':')) {
uwsgi_log("uwsgi shared socket %d inherited TCP address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), sock, i);
shared_sock->family = AF_INET;
-1
View File
@@ -108,7 +108,6 @@ pid_t spooler_start(struct uwsgi_spooler * uspool) {
signal(SIGSTOP, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
uwsgi.mywid = -1;
uwsgi.mypid = getpid();
uspool->pid = uwsgi.mypid;
// avoid race conditions !!!
-57
View File
@@ -1,57 +0,0 @@
#ifdef UWSGI_SQLITE3
#include "uwsgi.h"
#include <sqlite3.h>
extern struct uwsgi_server uwsgi;
static int uwsgi_sqlite3_config_callback(void *magic_table, int field_count, char **fields, char **col) {
// make a copy of the string
if (field_count >= 2) {
size_t value_len = strlen(fields[1]) + 1;
char *value = magic_sub(fields[1], value_len, &value_len, (char **) magic_table);
add_exported_option(uwsgi_strncopy(fields[0], strlen(fields[0])), value, 0);
}
return 0;
}
void uwsgi_sqlite3_config(char *file, char *magic_table[]) {
sqlite3 *db;
char *err = NULL;
char *query = "SELECT * FROM uwsgi";
char *colon = uwsgi_get_last_char(file, ':');
if (colon) {
colon[0] = 0;
if (colon[1] != 0) {
query = colon + 1;
}
}
uwsgi_log("[uWSGI] getting sqlite3 configuration from %s\n", file);
#ifdef sqlite3_open_v2
if (sqlite3_open_v2(file, &db, SQLITE_OPEN_READONLY, NULL)) {
#else
if (sqlite3_open(file, &db)) {
#endif
uwsgi_log("unable to open sqlite3 db: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
exit(1);
}
if (sqlite3_exec(db, query, uwsgi_sqlite3_config_callback, (void *) magic_table, &err)) {
uwsgi_log("sqlite3 error: %s\n", err);
sqlite3_close(db);
exit(1);
}
sqlite3_close(db);
}
#endif
+8 -2
View File
@@ -252,8 +252,14 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
uwsgi.ssl_sessions_cache = uwsgi_cache_by_name(uwsgi.ssl_sessions_use_cache);
if (!uwsgi.ssl_sessions_cache) {
uwsgi_log("unable to find cache \"%s\"\n", uwsgi.ssl_sessions_use_cache ? uwsgi.ssl_sessions_use_cache : "default");
exit(1);
// check for default cache
if (!strcmp(uwsgi.ssl_sessions_use_cache, "true") && uwsgi.caches) {
uwsgi.ssl_sessions_cache = uwsgi.caches;
}
else {
uwsgi_log("unable to find cache \"%s\"\n", uwsgi.ssl_sessions_use_cache ? uwsgi.ssl_sessions_use_cache : "default");
exit(1);
}
}
if (!uwsgi.ssl_sessions_cache->max_items) {
+62 -27
View File
@@ -55,7 +55,7 @@ gzip:
return 1;
}
static int set_http_date(time_t t, char *dst) {
int uwsgi_http_date(time_t t, char *dst) {
static char *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
static char *months[] = {
@@ -179,7 +179,7 @@ int uwsgi_add_expires_type(struct wsgi_request *wsgi_req, char *mime_type, int m
while (udd) {
if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(now + delta, expires);
int size = uwsgi_http_date(now + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
@@ -192,7 +192,7 @@ int uwsgi_add_expires_type(struct wsgi_request *wsgi_req, char *mime_type, int m
while (udd) {
if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(st->st_mtime + delta, expires);
int size = uwsgi_http_date(st->st_mtime + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
@@ -215,7 +215,7 @@ int uwsgi_add_expires(struct wsgi_request *wsgi_req, char *filename, int filenam
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, filename, filename_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(now + delta, expires);
int size = uwsgi_http_date(now + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
@@ -228,7 +228,7 @@ int uwsgi_add_expires(struct wsgi_request *wsgi_req, char *filename, int filenam
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, filename, filename_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(st->st_mtime + delta, expires);
int size = uwsgi_http_date(st->st_mtime + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
@@ -250,7 +250,7 @@ int uwsgi_add_expires_path_info(struct wsgi_request *wsgi_req, struct stat *st)
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->path_info, wsgi_req->path_info_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(now + delta, expires);
int size = uwsgi_http_date(now + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
@@ -263,7 +263,7 @@ int uwsgi_add_expires_path_info(struct wsgi_request *wsgi_req, struct stat *st)
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->path_info, wsgi_req->path_info_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(st->st_mtime + delta, expires);
int size = uwsgi_http_date(st->st_mtime + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
@@ -285,7 +285,7 @@ int uwsgi_add_expires_uri(struct wsgi_request *wsgi_req, struct stat *st) {
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(now + delta, expires);
int size = uwsgi_http_date(now + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
@@ -298,7 +298,7 @@ int uwsgi_add_expires_uri(struct wsgi_request *wsgi_req, struct stat *st) {
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(st->st_mtime + delta, expires);
int size = uwsgi_http_date(st->st_mtime + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
@@ -315,7 +315,7 @@ int uwsgi_add_expires_uri(struct wsgi_request *wsgi_req, struct stat *st) {
#endif
char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
char *uwsgi_get_mime_type(char *name, int namelen, size_t *size) {
int i;
int count = 0;
@@ -333,6 +333,10 @@ char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
if (!ext)
return NULL;
if (uwsgi.threads > 1)
pthread_mutex_lock(&uwsgi.lock_static);
struct uwsgi_dyn_dict *udd = uwsgi.mimetypes;
while (udd) {
if (!uwsgi_strncmp(ext, count, udd->key, udd->keylen)) {
@@ -361,11 +365,16 @@ char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
}
}
*size = udd->vallen;
if (uwsgi.threads > 1)
pthread_mutex_unlock(&uwsgi.lock_static);
return udd->value;
}
udd = udd->next;
}
if (uwsgi.threads > 1)
pthread_mutex_unlock(&uwsgi.lock_static);
return NULL;
}
@@ -429,16 +438,14 @@ static int uwsgi_static_stat(struct wsgi_request *wsgi_req, char *filename, size
int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, size_t real_filename_len, struct stat *st) {
int mime_type_size = 0;
size_t mime_type_size = 0;
char http_last_modified[49];
if (uwsgi.threads > 1)
pthread_mutex_lock(&uwsgi.lock_static);
int use_gzip = 0;
char *mime_type = uwsgi_get_mime_type(real_filename, real_filename_len, &mime_type_size);
if (uwsgi.threads > 1)
pthread_mutex_unlock(&uwsgi.lock_static);
// here we need to choose if we want the gzip variant;
if (uwsgi_static_want_gzip(wsgi_req, real_filename, real_filename_len, st)) use_gzip = 1;
if (wsgi_req->if_modified_since_len) {
time_t ims = parse_http_date(wsgi_req->if_modified_since, wsgi_req->if_modified_since_len);
@@ -451,8 +458,32 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
uwsgi_log("[uwsgi-fileserve] file %s found\n", real_filename);
#endif
size_t fsize = st->st_size;
if (wsgi_req->range_to) {
fsize = wsgi_req->range_to - wsgi_req->range_from;
if (fsize > (size_t)st->st_size) {
fsize = st->st_size;
}
}
else {
// reset in case of inconsistent size
if (wsgi_req->range_from > fsize) {
wsgi_req->range_from = 0;
fsize = 0;
}
else {
fsize -= wsgi_req->range_from;
}
}
// HTTP status
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
if (fsize > 0 && (wsgi_req->range_from || wsgi_req->range_to)) {
if (uwsgi_response_prepare_headers(wsgi_req, "206 Partial Content", 19)) return -1;
}
else {
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
}
#ifdef UWSGI_PCRE
uwsgi_add_expires(wsgi_req, real_filename, real_filename_len, st);
@@ -460,6 +491,10 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
uwsgi_add_expires_uri(wsgi_req, st);
#endif
if (use_gzip) {
if (uwsgi_response_add_header(wsgi_req, "Content-Encoding", 16, "gzip", 4)) return -1;
}
// Content-Type (if available)
if (mime_type_size > 0 && mime_type) {
if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_size)) return -1;
@@ -474,25 +509,25 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
if (uwsgi.file_serve_mode == 1) {
if (uwsgi_response_add_header(wsgi_req, "X-Accel-Redirect", 16, real_filename, real_filename_len)) return -1;
// this is the final header (\r\n added)
int size = set_http_date(st->st_mtime, http_last_modified);
int size = uwsgi_http_date(st->st_mtime, http_last_modified);
if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1;
}
// apache
else if (uwsgi.file_serve_mode == 2) {
if (uwsgi_response_add_header(wsgi_req, "X-Sendfile", 10, real_filename, real_filename_len)) return -1;
// this is the final header (\r\n added)
int size = set_http_date(st->st_mtime, http_last_modified);
int size = uwsgi_http_date(st->st_mtime, http_last_modified);
if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1;
}
// raw
else {
// here we need to choose if we want the gzip variant;
if (uwsgi_static_want_gzip(wsgi_req, real_filename, real_filename_len, st)) {
if (uwsgi_response_add_header(wsgi_req, "Content-Encoding", 16, "gzip", 4)) return -1;
// set Content-Length (to fsize NOT st->st_size)
if (uwsgi_response_add_content_length(wsgi_req, fsize)) return -1;
if (fsize > 0 && (wsgi_req->range_from || wsgi_req->range_to)) {
// here use the original size !!!
if (uwsgi_response_add_content_range(wsgi_req, wsgi_req->range_from, wsgi_req->range_to, st->st_size)) return -1;
}
// set Content-Length
if (uwsgi_response_add_content_length(wsgi_req, st->st_size)) return -1;
int size = set_http_date(st->st_mtime, http_last_modified);
int size = uwsgi_http_date(st->st_mtime, http_last_modified);
if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1;
// if it is a HEAD request just skip transfer
@@ -506,7 +541,7 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
int fd = open(real_filename, O_RDONLY);
if (fd < 0) return -1;
// fd will be closed in the following function
uwsgi_response_sendfile_do(wsgi_req, fd, 0, st->st_size);
uwsgi_response_sendfile_do(wsgi_req, fd, wsgi_req->range_from, fsize);
}
wsgi_req->status = 200;
@@ -609,7 +644,7 @@ safe:
#ifdef UWSGI_ROUTING
// before sending the file, we need to check if some rule applies
if (uwsgi_apply_routes_do(wsgi_req, NULL, 0) == UWSGI_ROUTE_BREAK) {
if (!wsgi_req->is_routing && uwsgi_apply_routes_do(wsgi_req, NULL, 0) == UWSGI_ROUTE_BREAK) {
return 0;
}
wsgi_req->routes_applied = 1;
+43 -1
View File
@@ -315,6 +315,45 @@ int uwsgi_stats_keylong_comma(struct uwsgi_stats *us, char *key, unsigned long l
return uwsgi_stats_comma(us);
}
int uwsgi_stats_keyslong(struct uwsgi_stats *us, char *key, long long num) {
if (uwsgi_stats_apply_tabs(us))
return -1;
char *ptr = us->base + us->pos;
char *watermark = us->base + us->size;
size_t available = watermark - ptr;
int ret = snprintf(ptr, available, "\"%s\":%lld", key, num);
if (ret < 0)
return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
if (!new_base)
return -1;
us->base = new_base;
us->size += us->chunk;
ptr = us->base + us->pos;
watermark = us->base + us->size;
available = watermark - ptr;
ret = snprintf(ptr, available, "\"%s\":%lld", key, num);
if (ret < 0)
return -1;
}
us->pos += ret;
return 0;
}
int uwsgi_stats_keyslong_comma(struct uwsgi_stats *us, char *key, long long num) {
int ret = uwsgi_stats_keyslong(us, key, num);
if (ret)
return -1;
return uwsgi_stats_comma(us);
}
void uwsgi_send_stats(int fd, struct uwsgi_stats *(*func) (void)) {
struct sockaddr_un client_src;
@@ -383,7 +422,10 @@ struct uwsgi_stats_pusher_instance *uwsgi_stats_pusher_add(struct uwsgi_stats_pu
uspi = uwsgi_calloc(sizeof(struct uwsgi_stats_pusher_instance));
uspi->pusher = pusher;
uspi->arg = arg;
if (arg) {
uspi->arg = uwsgi_str(arg);
}
uspi->raw = pusher->raw;
if (old_uspi) {
old_uspi->next = uspi;
}
+69
View File
@@ -0,0 +1,69 @@
#include <uwsgi.h>
/*
uWSGI transformations
responses can be buffered in the wsgi_request structure (instead of being sent to the client)
Before closing the request, the transformations are applied in chain to the response buffer
Finally the resulting buffer is sent to the client
Transformations (if required) could completely swallow already set headers
*/
extern struct uwsgi_server uwsgi;
int uwsgi_apply_transformations(struct wsgi_request *wsgi_req) {
int ret = 0;
struct uwsgi_transformation *ut = wsgi_req->transformations;
while(ut) {
struct uwsgi_buffer *new_ub = NULL;
if (ut->func(wsgi_req, wsgi_req->response_buffer, &new_ub, ut->data)) {
ret = -1;
goto end;
}
if (new_ub) {
uwsgi_buffer_destroy(wsgi_req->response_buffer);
wsgi_req->response_buffer = new_ub;
}
ut = ut->next;
}
end:
ut = wsgi_req->transformations;
while(ut) {
struct uwsgi_transformation *current_ut = ut;
ut = ut->next;
free(current_ut);
}
return ret;
}
struct uwsgi_transformation *uwsgi_add_transformation(struct wsgi_request *wsgi_req, int (*func)(struct wsgi_request *, struct uwsgi_buffer *, struct uwsgi_buffer **, void *), void *data) {
struct uwsgi_transformation *old_ut = NULL, *ut = wsgi_req->transformations;
while(ut) {
old_ut = ut;
ut = ut->next;
}
ut = uwsgi_malloc(sizeof(struct uwsgi_transformation));
ut->func = func;
ut->next = NULL;
ut->data = data;
if (old_ut) {
old_ut->next = ut;
}
else {
wsgi_req->transformations = ut;
}
// start buffering
if (!wsgi_req->response_buffer) {
wsgi_req->response_buffer = uwsgi_buffer_new(uwsgi.page_size);
}
return ut;
}
+122 -16
View File
@@ -222,12 +222,11 @@ void uwsgi_set_cgroup() {
uwsgi_error_open(cgroup_taskfile);
exit(1);
}
if (fprintf(cgroup, "%d", (int) getpid()) <= 0) {
uwsgi_log("could not set cgroup\n");
if (fprintf(cgroup, "%d\n", (int) getpid()) <= 0 || ferror(cgroup) || fclose(cgroup)) {
uwsgi_error("could not set cgroup");
exit(1);
}
uwsgi_log("assigned process %d to cgroup %s\n", (int) getpid(), cgroup_taskfile);
fclose(cgroup);
free(cgroup_taskfile);
@@ -248,11 +247,10 @@ void uwsgi_set_cgroup() {
cgroup_taskfile = uwsgi_concat3(usl->value, "/", uslo->value);
cgroup = fopen(cgroup_taskfile, "w");
if (cgroup) {
if (fprintf(cgroup, "%s\n", cgroup_opt) < 0) {
if (fprintf(cgroup, "%s\n", cgroup_opt) <= 0 || ferror(cgroup) || fclose(cgroup)) {
uwsgi_log("could not set cgroup option %s to %s\n", uslo->value, cgroup_opt);
exit(1);
}
fclose(cgroup);
uwsgi_log("set %s to %s\n", cgroup_opt, cgroup_taskfile);
}
free(cgroup_taskfile);
@@ -576,6 +574,25 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
int tmp_id;
uint64_t tmp_rt, rss = 0, vsz = 0;
// flush the response buf (if any)
if (wsgi_req->response_buffer) {
// send the body only if transformations are successfull
struct uwsgi_buffer *ub = wsgi_req->response_buffer;
if (uwsgi_apply_transformations(wsgi_req) == 0) {
// the response_buffer could be changed by translations
ub = wsgi_req->response_buffer;
// force true write (take flushing into account)
wsgi_req->response_buffer = NULL;
if (wsgi_req->response_size == 0) {
uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
}
}
else {
wsgi_req->write_errors++;
}
uwsgi_buffer_destroy(ub);
}
// check if headers should be sent
if (wsgi_req->headers) {
if (!wsgi_req->headers_sent && !wsgi_req->headers_size && !wsgi_req->response_size) {
@@ -599,7 +616,6 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
uwsgi.workers[uwsgi.mywid].rss_size = rss;
}
// close the connection with the client
if (!wsgi_req->fd_closed) {
// NOTE, if we close the socket before receiving eventually sent data, socket layer will send a RST
@@ -1122,11 +1138,36 @@ void parse_sys_envs(char **envs) {
}
// get the application id
int uwsgi_get_app_id(char *app_name, int app_name_len, int modifier1) {
int uwsgi_get_app_id(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, int modifier1) {
int i;
struct stat st;
int found;
int free_appname = 0;
char *app_name = key;
uint16_t app_name_len = key_len;
if (!app_name && wsgi_req) {
app_name = wsgi_req->appid;
app_name_len = wsgi_req->appid_len;
if (app_name_len == 0) {
if (!uwsgi.ignore_script_name) {
app_name = wsgi_req->script_name;
app_name_len = wsgi_req->script_name_len;
}
if (uwsgi.vhost) {
app_name = uwsgi_concat3n(wsgi_req->host, wsgi_req->host_len, "|",1, wsgi_req->script_name, wsgi_req->script_name_len);
app_name_len = wsgi_req->host_len + 1 + wsgi_req->script_name_len;
#ifdef UWSGI_DEBUG
uwsgi_debug("VirtualHost KEY=%.*s\n", wsgi_req->appid_len, wsgi_req->appid);
#endif
free_appname = 1;
}
}
}
for (i = 0; i < uwsgi_apps_cnt; i++) {
// reset check
@@ -1158,14 +1199,19 @@ int uwsgi_get_app_id(char *app_name, int app_name_len, int modifier1) {
}
}
}
if (modifier1 == -1)
if (modifier1 == -1) {
if (free_appname) free(app_name);
return i;
if (modifier1 == uwsgi_apps[i].modifier1)
}
if (modifier1 == uwsgi_apps[i].modifier1) {
if (free_appname) free(app_name);
return i;
}
}
}
if (!uwsgi.no_default_app) {
if (free_appname) free(app_name);
return uwsgi.default_app;
}
@@ -1506,6 +1552,25 @@ int uwsgi_logic_opt_for_glob(char *key, char *value) {
return 1;
}
int uwsgi_logic_opt_for_times(char *key, char *value) {
int num = atoi(uwsgi.logic_opt_data);
int i;
char str_num[11];
for (i = 1; i <= num; i++) {
int ret = uwsgi_num2str2(i, str_num);
// security check
if (ret < 0 || ret > 11) {
exit(1);
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", str_num), 0);
}
return 1;
}
void add_exported_option(char *key, char *value, int configured) {
@@ -2470,13 +2535,19 @@ void uwsgi_chown(char *filename, char *owner) {
char *uwsgi_get_binary_path(char *argvzero) {
#if defined(__linux__)
#if defined(__linux__) || defined(__CYGWIN__)
char *buf = uwsgi_calloc(PATH_MAX + 1);
ssize_t len = readlink("/proc/self/exe", buf, PATH_MAX);
if (len > 0) {
return buf;
}
free(buf);
#elif defined(_WIN32)
char *buf = uwsgi_calloc(PATH_MAX + 1);
if (GetModuleFileName(NULL, buf, PATH_MAX) > 0) {
return buf;
}
free(buf);
#elif defined(__NetBSD__)
char *buf = uwsgi_calloc(PATH_MAX + 1);
ssize_t len = readlink("/proc/curproc/exe", buf, PATH_MAX);
@@ -2941,11 +3012,13 @@ pid_t uwsgi_fork(char *name) {
pid_t pid = fork();
if (pid == 0) {
#ifndef __CYGWIN__
if (uwsgi.never_swap) {
if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
uwsgi_error("mlockall()");
}
}
#endif
#if defined(__linux__) || defined(__sun__)
int i;
@@ -3027,14 +3100,17 @@ void http_url_decode(char *buf, uint16_t * len, char *dst) {
}
/*
we scan the table in reverse, as updated values are at the end
*/
char *uwsgi_get_var(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t * len) {
int i;
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
if (!uwsgi_strncmp(key, keylen, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len)) {
*len = wsgi_req->hvec[i + 1].iov_len;
return wsgi_req->hvec[i + 1].iov_base;
for (i = wsgi_req->var_cnt-1; i > 0; i -= 2) {
if (!uwsgi_strncmp(key, keylen, wsgi_req->hvec[i-1].iov_base, wsgi_req->hvec[i-1].iov_len)) {
*len = wsgi_req->hvec[i].iov_len;
return wsgi_req->hvec[i].iov_base;
}
}
@@ -3187,10 +3263,9 @@ void uwsgi_write_pidfile(char *pidfile_name) {
uwsgi_error_open(pidfile_name);
exit(1);
}
if (fprintf(pidfile, "%d\n", (int) getpid()) < 0) {
if (fprintf(pidfile, "%d\n", (int) getpid()) <= 0 || ferror(pidfile) || fclose(pidfile)) {
uwsgi_log("could not write pidfile.\n");
}
fclose(pidfile);
}
char *uwsgi_expand_path(char *dir, int dir_len, char *ptr) {
@@ -3453,6 +3528,7 @@ int uwsgi_kvlist_parse(char *src, size_t len, char list_separator, char kv_separ
escaped = 1;
}
else if (escaped) {
*ptr++ = src[i];
escaped = 0;
}
else {
@@ -3801,3 +3877,33 @@ char *uwsgi_get_header(struct wsgi_request *wsgi_req, char *hh, uint16_t len, ui
return value;
}
static char *uwsgi_hex_table[] = {
"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F",
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F",
"20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F",
"30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F",
"40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F",
"50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F",
"60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F",
"70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D", "7E", "7F",
"80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F",
"90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F",
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF",
"B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF",
"C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF",
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF",
"E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
"F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF",
};
char *uwsgi_str_to_hex(char *src, size_t slen) {
char *dst = uwsgi_malloc(slen*2);
char *ptr = dst;
size_t i;
for(i=0;i<slen;i++) {
memcpy(ptr, uwsgi_hex_table[ (int) src[i] ], 2);
ptr+=2;
}
return dst;
}
+192 -55
View File
@@ -24,6 +24,7 @@
#include <uwsgi.h>
struct uwsgi_server uwsgi;
pid_t masterpid;
#if defined(__APPLE__) && defined(UWSGI_AS_SHARED_LIBRARY)
#include <crt_externs.h>
@@ -70,8 +71,10 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"xmlconfig", required_argument, 'x', "load config from xml file", uwsgi_opt_load_xml, NULL, UWSGI_OPT_IMMEDIATE},
{"xml", required_argument, 'x', "load config from xml file", uwsgi_opt_load_xml, NULL, UWSGI_OPT_IMMEDIATE},
#endif
{"config", required_argument, 0, "load configuration using the pluggable system", uwsgi_opt_load_config, NULL, UWSGI_OPT_IMMEDIATE},
{"skip-zero", no_argument, 0, "skip check of file descriptor 0", uwsgi_opt_true, &uwsgi.skip_zero, 0},
{"skip-atexit", no_argument, 0, "skip atexit hooks (ignored by the master)", uwsgi_opt_true, &uwsgi.skip_atexit, 0},
{"set", required_argument, 'S', "set a custom placeholder", uwsgi_opt_set_placeholder, NULL, UWSGI_OPT_IMMEDIATE},
{"get", required_argument, 0, "print the specified option value and exit", uwsgi_opt_add_string_list, &uwsgi.get_list, UWSGI_OPT_NO_INITIAL},
@@ -79,7 +82,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"for", required_argument, 0, "(opt logic) for cycle", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for, UWSGI_OPT_IMMEDIATE},
{"for-glob", required_argument, 0, "(opt logic) for cycle (expand glob)", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for_glob, UWSGI_OPT_IMMEDIATE},
{"for-times", required_argument, 0, "(opt logic) for cycle (expand the specified num to a list starting from 1)", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for_times, UWSGI_OPT_IMMEDIATE},
{"endfor", optional_argument, 0, "(opt logic) end for cycle", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
{"end-for", optional_argument, 0, "(opt logic) end for cycle", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
{"if-opt", required_argument, 0, "(opt logic) check for option", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_opt, UWSGI_OPT_IMMEDIATE},
{"if-not-opt", required_argument, 0, "(opt logic) check for option", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_not_opt, UWSGI_OPT_IMMEDIATE},
@@ -108,6 +113,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"if-directory", required_argument, 0, "(opt logic) check for directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_dir, UWSGI_OPT_IMMEDIATE},
{"endif", optional_argument, 0, "(opt logic) end if", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
{"end-if", optional_argument, 0, "(opt logic) end if", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
{"blacklist", required_argument, 0, "set options blacklist context", uwsgi_opt_set_str, &uwsgi.blacklist_context, UWSGI_OPT_IMMEDIATE},
{"end-blacklist", no_argument, 0, "clear options blacklist context", uwsgi_opt_set_null, &uwsgi.blacklist_context, UWSGI_OPT_IMMEDIATE},
@@ -163,12 +169,14 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"single-interpreter", no_argument, 'i', "do not use multiple interpreters (where available)", uwsgi_opt_true, &uwsgi.single_interpreter, 0},
{"need-app", no_argument, 0, "exit if no app can be loaded", uwsgi_opt_true, &uwsgi.need_app, 0},
{"master", no_argument, 'M', "enable master process", uwsgi_opt_true, &uwsgi.master_process, 0},
{"honour-stdin", no_argument, 0, "do not remap stdin to /dev/null", uwsgi_opt_true, &uwsgi.honour_stdin, 0},
{"emperor", required_argument, 0, "run the Emperor", uwsgi_opt_add_string_list, &uwsgi.emperor, 0},
{"emperor-procname", required_argument, 0, "set the Emperor process name", uwsgi_opt_set_str, &uwsgi.emperor_procname, 0},
{"emperor-freq", required_argument, 0, "set the Emperor scan frequency (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.emperor_freq, 0},
{"emperor-required-heartbeat", required_argument, 0, "set the Emperor tolerance about heartbeats", uwsgi_opt_set_int, &uwsgi.emperor_heartbeat, 0},
{"emperor-pidfile", required_argument, 0, "write the Emperor pid in the specified file", uwsgi_opt_set_str, &uwsgi.emperor_pidfile, 0},
{"emperor-tyrant", no_argument, 0, "put the Emperor in Tyrant mode", uwsgi_opt_true, &uwsgi.emperor_tyrant, 0},
{"emperor-tyrant-nofollow", no_argument, 0, "do not follow symlinks when checking for uid/gid in Tyrant mode", uwsgi_opt_true, &uwsgi.emperor_tyrant_nofollow, 0},
{"emperor-stats", required_argument, 0, "run the Emperor stats server", uwsgi_opt_set_str, &uwsgi.emperor_stats, 0},
{"emperor-stats-server", required_argument, 0, "run the Emperor stats server", uwsgi_opt_set_str, &uwsgi.emperor_stats, 0},
{"early-emperor", no_argument, 0, "spawn the emperor as soon as possibile", uwsgi_opt_true, &uwsgi.early_emperor, 0},
@@ -176,6 +184,13 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"emperor-throttle", required_argument, 0, "set throttling level (in milliseconds) for bad behaving vassals (default 1000)", uwsgi_opt_set_int, &uwsgi.emperor_throttle, 0},
{"emperor-max-throttle", required_argument, 0, "set max throttling level (in milliseconds) for bad behaving vassals (default 3 minutes)", uwsgi_opt_set_int, &uwsgi.emperor_max_throttle, 0},
{"emperor-magic-exec", no_argument, 0, "prefix vassals config files with exec:// if they have the executable bit", uwsgi_opt_true, &uwsgi.emperor_magic_exec, 0},
{"emperor-on-demand-extension", required_argument, 0, "search for text file (vassal name + extension) containing the on demand socket name", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_extension, 0},
{"emperor-on-demand-ext", required_argument, 0, "search for text file (vassal name + extension) containing the on demand socket name", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_extension, 0},
{"emperor-on-demand-directory", required_argument, 0, "enable on demand mode binding to the unix socket in the specified directory named like the vassal + .socket", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_directory, 0},
{"emperor-on-demand-dir", required_argument, 0, "enable on demand mode binding to the unix socket in the specified directory named like the vassal + .socket", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_directory, 0},
{"emperor-on-demand-exec", required_argument, 0, "use the output of the specified command as on demand socket name (the vassal name is passed as the only argument)", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_exec, 0},
{"emperor-extra-extension", required_argument, 0, "allows the specified extension in the Emperor (vassal will be called with --config)", uwsgi_opt_add_string_list, &uwsgi.emperor_extra_extension, 0},
{"emperor-extra-ext", required_argument, 0, "allows the specified extension in the Emperor (vassal will be called with --config)", uwsgi_opt_add_string_list, &uwsgi.emperor_extra_extension, 0},
{"imperial-monitor-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0},
{"imperial-monitors-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0},
{"vassals-inherit", required_argument, 0, "add config templates to vassals config", uwsgi_opt_add_string_list, &uwsgi.vassals_templates, 0},
@@ -203,6 +218,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"ftok", required_argument, 0, "set the ipcsem key via ftok() for avoiding duplicates", uwsgi_opt_set_str, &uwsgi.ftok, 0},
{"sharedarea", required_argument, 'A', "create a raw shared memory area of specified pages", uwsgi_opt_set_int, &uwsgi.sharedareasize, 0},
{"safe-fd", no_argument, 0, "do not close the specified file descriptor", uwsgi_opt_safe_fd, NULL, 0},
{"fd-safe", no_argument, 0, "do not close the specified file descriptor", uwsgi_opt_safe_fd, NULL, 0},
{"cache", required_argument, 0, "create a shared cache containing given elements", uwsgi_opt_set_64bit, &uwsgi.cache_max_items, 0},
{"cache-blocksize", required_argument, 0, "set cache blocksize", uwsgi_opt_set_64bit, &uwsgi.cache_blocksize, 0},
{"cache-store", required_argument, 0, "enable persistent cache to disk", uwsgi_opt_set_str, &uwsgi.cache_store, UWSGI_OPT_MASTER},
@@ -213,8 +231,12 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"cache-udp-server", required_argument, 0, "bind the cache udp server (used only for set/update/delete) to the specified socket", uwsgi_opt_add_string_list, &uwsgi.cache_udp_server, UWSGI_OPT_MASTER},
{"cache-udp-node", required_argument, 0, "send cache update/deletion to the specified cache udp server", uwsgi_opt_add_string_list, &uwsgi.cache_udp_node, UWSGI_OPT_MASTER},
{"cache-sync", required_argument, 0, "copy the whole content of another uWSGI cache server on server startup", uwsgi_opt_set_str, &uwsgi.cache_sync, 0},
{"cache-use-last-modified", no_argument, 0, "update last_modified_at timestamp on every cache item modification (default is disabled)", uwsgi_opt_true, &uwsgi.cache_use_last_modified, 0},
{"load-file-in-cache", required_argument, 0, "load a static file in the cache", uwsgi_opt_add_string_list, &uwsgi.load_file_in_cache, 0},
#ifdef UWSGI_ZLIB
{"load-file-in-cache-gzip", required_argument, 0, "load a static file in the cache with gzip compression", uwsgi_opt_add_string_list, &uwsgi.load_file_in_cache_gzip, 0},
#endif
{"cache2", required_argument, 0, "create a new generation shared cache (keyval syntax)", uwsgi_opt_add_string_list, &uwsgi.cache2, 0},
@@ -256,6 +278,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"chroot", required_argument, 0, "chroot() to the specified directory", uwsgi_opt_set_str, &uwsgi.chroot, 0},
{"uid", required_argument, 0, "setuid to the specified user/uid", uwsgi_opt_set_uid, NULL, 0},
{"gid", required_argument, 0, "setgid to the specified group/gid", uwsgi_opt_set_gid, NULL, 0},
{"immediate-uid", required_argument, 0, "setuid to the specified user/uid IMMEDIATELY", uwsgi_opt_set_immediate_uid, NULL, UWSGI_OPT_IMMEDIATE},
{"immediate-gid", required_argument, 0, "setgid to the specified group/gid IMMEDIATELY", uwsgi_opt_set_immediate_gid, NULL, UWSGI_OPT_IMMEDIATE},
{"no-initgroups", no_argument, 0, "disable additional groups set via initgroups()", uwsgi_opt_true, &uwsgi.no_initgroups, 0},
#ifdef UWSGI_CAP
{"cap", required_argument, 0, "set process capability", uwsgi_opt_set_cap, NULL, 0},
@@ -270,9 +294,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"exec-as-user", required_argument, 0, "run the specified command after privileges drop", uwsgi_opt_add_string_list, &uwsgi.exec_as_user, 0},
{"exec-as-user-atexit", required_argument, 0, "run the specified command before app exit and reload", uwsgi_opt_add_string_list, &uwsgi.exec_as_user_atexit, 0},
{"exec-pre-app", required_argument, 0, "run the specified command before app loading", uwsgi_opt_add_string_list, &uwsgi.exec_pre_app, 0},
#ifdef UWSGI_INI
{"exec-post-app", required_argument, 0, "run the specified command after app loading", uwsgi_opt_add_string_list, &uwsgi.exec_post_app, 0},
{"ini", required_argument, 0, "load config from ini file", uwsgi_opt_load_ini, NULL, UWSGI_OPT_IMMEDIATE},
#endif
#ifdef UWSGI_YAML
{"yaml", required_argument, 'y', "load config from yaml file", uwsgi_opt_load_yml, NULL, UWSGI_OPT_IMMEDIATE},
{"yal", required_argument, 'y', "load config from yaml file", uwsgi_opt_load_yml, NULL, UWSGI_OPT_IMMEDIATE},
@@ -281,20 +304,11 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"json", required_argument, 'j', "load config from json file", uwsgi_opt_load_json, NULL, UWSGI_OPT_IMMEDIATE},
{"js", required_argument, 'j', "load config from json file", uwsgi_opt_load_json, NULL, UWSGI_OPT_IMMEDIATE},
#endif
#ifdef UWSGI_SQLITE3
{"sqlite3", required_argument, 0, "load config from sqlite3 db", uwsgi_opt_load_sqlite3, NULL, UWSGI_OPT_IMMEDIATE},
{"sqlite", required_argument, 0, "load config from sqlite3 db", uwsgi_opt_load_sqlite3, NULL, UWSGI_OPT_IMMEDIATE},
#endif
#ifdef UWSGI_ZEROMQ
{"zeromq", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
{"zmq", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
{"zeromq-socket", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
{"zmq-socket", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
#endif
#ifdef UWSGI_LDAP
{"ldap", required_argument, 0, "load configuration from ldap server", uwsgi_opt_load_ldap, NULL, UWSGI_OPT_IMMEDIATE},
{"ldap-schema", no_argument, 0, "dump uWSGI ldap schema", uwsgi_opt_ldap_dump, NULL, UWSGI_OPT_IMMEDIATE},
{"ldap-schema-ldif", no_argument, 0, "dump uWSGI ldap schema in ldif format", uwsgi_opt_ldap_dump_ldif, NULL, UWSGI_OPT_IMMEDIATE},
#endif
{"weight", required_argument, 0, "weight of the instance (used by clustering/lb/subscriptions)", uwsgi_opt_set_64bit, &uwsgi.weight, 0},
{"auto-weight", required_argument, 0, "set weight of the instance (used by clustering/lb/subscriptions) automatically", uwsgi_opt_true, &uwsgi.auto_weight, 0},
@@ -307,6 +321,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"socket-send-timeout", no_argument, 0, "set SO_SNDTIMEO", uwsgi_opt_set_int, &uwsgi.so_send_timeout, 0},
{"so-write-timeout", no_argument, 0, "set SO_SNDTIMEO", uwsgi_opt_set_int, &uwsgi.so_send_timeout, 0},
{"socket-write-timeout", no_argument, 0, "set SO_SNDTIMEO", uwsgi_opt_set_int, &uwsgi.so_send_timeout, 0},
{"socket-sndbuf", required_argument, 0, "set SO_SNDBUF", uwsgi_opt_set_64bit, &uwsgi.so_sndbuf, 0},
{"socket-rcvbuf", required_argument, 0, "set SO_RCVBUF", uwsgi_opt_set_64bit, &uwsgi.so_rcvbuf, 0},
{"limit-as", required_argument, 0, "limit processes address space/vsz", uwsgi_opt_set_megabytes, &uwsgi.rl.rlim_max, 0},
{"limit-nproc", required_argument, 0, "limit the number of spawnable processes", uwsgi_opt_set_int, &uwsgi.rl_nproc.rlim_max, 0},
{"reload-on-as", required_argument, 0, "reload if address space is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.reload_on_as, UWSGI_OPT_MEMORY},
@@ -363,6 +379,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
#ifdef UWSGI_SSL
{"legion", required_argument, 0, "became a member of a legion", uwsgi_opt_legion, NULL, UWSGI_OPT_MASTER},
{"legion-mcast", required_argument, 0, "became a member of a legion (shortcut for multicast)", uwsgi_opt_legion_mcast, NULL, UWSGI_OPT_MASTER},
{"legion-node", required_argument, 0, "add a node to a legion", uwsgi_opt_legion_node, NULL, UWSGI_OPT_MASTER},
{"legion-freq", required_argument, 0, "set the frequency of legion packets", uwsgi_opt_set_int, &uwsgi.legion_freq, UWSGI_OPT_MASTER},
{"legion-tolerance", required_argument, 0, "set the tolerance of legion subsystem", uwsgi_opt_set_int, &uwsgi.legion_tolerance, UWSGI_OPT_MASTER},
@@ -371,10 +388,13 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"legion-unlord", required_argument, 0, "action to call on Lord dismiss", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
{"legion-setup", required_argument, 0, "action to call on legion setup", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
{"legion-death", required_argument, 0, "action to call on legion death (shutdown of the instance)", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
{"legion-join", required_argument, 0, "action to call on legion join (first time quorum is reached)", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
{"legion-node-joined", required_argument, 0, "action to call on new node joining legion", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
{"legion-node-left", required_argument, 0, "action to call node leaving legion", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
{"legion-quorum", required_argument, 0, "set the quorum of a legion", uwsgi_opt_legion_quorum, NULL, UWSGI_OPT_MASTER},
{"legion-scroll", required_argument, 0, "set the scroll of a legion", uwsgi_opt_legion_scroll, NULL, UWSGI_OPT_MASTER},
{"legion-scroll", required_argument, 0, "set the scroll of a legion", uwsgi_opt_legion_scroll, NULL, UWSGI_OPT_MASTER},
{"legion-scroll-max-size", required_argument, 0, "set max size of legion scroll buffer", uwsgi_opt_set_16bit, &uwsgi.legion_scroll_max_size, 0},
{"legion-scroll-list-max-size", required_argument, 0, "set max size of legion scroll list buffer", uwsgi_opt_set_64bit, &uwsgi.legion_scroll_list_max_size, 0},
{"subscriptions-sign-check", required_argument, 0, "set digest algorithm and certificate directory for secured subscription system", uwsgi_opt_scd, NULL, UWSGI_OPT_MASTER},
{"subscriptions-sign-check-tolerance", required_argument, 0, "set the maximum tolerance (in seconds) of clock skew for secured subscription system", uwsgi_opt_set_int, &uwsgi.subscriptions_sign_check_tolerance, UWSGI_OPT_MASTER},
#endif
@@ -436,6 +456,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
#endif
{"alarm", required_argument, 0, "create a new alarm, syntax: <alarm> <plugin:args>", uwsgi_opt_add_string_list, &uwsgi.alarm_list, UWSGI_OPT_MASTER},
{"alarm-freq", required_argument, 0, "tune the anti-loop alam system (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.alarm_freq, 0},
{"alarm-fd", required_argument, 0, "raise the specified alarm when an fd is read for read (by default it reads 1 byte, set 8 for eventfd)", uwsgi_opt_add_string_list, &uwsgi.alarm_fd_list, UWSGI_OPT_MASTER},
#ifdef UWSGI_PCRE
{"log-alarm", required_argument, 0, "raise the specified alarm when a log line matches the specified regexp, syntax: <alarm>[,alarm...] <regexp>", uwsgi_opt_add_string_list, &uwsgi.alarm_logs_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
{"alarm-log", required_argument, 0, "raise the specified alarm when a log line matches the specified regexp, syntax: <alarm>[,alarm...] <regexp>", uwsgi_opt_add_string_list, &uwsgi.alarm_logs_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
@@ -506,6 +527,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"route-label", required_argument, 0, "add a routing label (for use with goto)", uwsgi_opt_add_route, NULL, 0},
{"route-if", required_argument, 0, "add a route based on condition", uwsgi_opt_add_route, "if", 0},
{"route-if-not", required_argument, 0, "add a route based on condition (negate version)", uwsgi_opt_add_route, "if-not", 0},
{"route-run", required_argument, 0, "always run the specified route action", uwsgi_opt_add_route, "run", 0},
{"router-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0},
{"routers-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0},
#endif
@@ -561,6 +583,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"static-gzip-ext", required_argument, 0, "check for a gzip version of all requested static files with the specified ext/suffix", uwsgi_opt_add_string_list, &uwsgi.static_gzip_ext, UWSGI_OPT_MIME},
{"static-gzip-suffix", required_argument, 0, "check for a gzip version of all requested static files with the specified ext/suffix", uwsgi_opt_add_string_list, &uwsgi.static_gzip_ext, UWSGI_OPT_MIME},
{"honour-range", no_argument, 0, "enable support for the HTTP Range header", uwsgi_opt_true, &uwsgi.honour_range, 0},
{"offload-threads", required_argument, 0, "set the number of offload threads to spawn (per-worker, default 0)", uwsgi_opt_set_int, &uwsgi.offload_threads, 0},
{"offload-thread", required_argument, 0, "set the number of offload threads to spawn (per-worker, default 0)", uwsgi_opt_set_int, &uwsgi.offload_threads, 0},
@@ -573,6 +597,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"env", required_argument, 0, "set environment variable", uwsgi_opt_set_env, NULL, 0},
{"unenv", required_argument, 0, "unset environment variable", uwsgi_opt_unset_env, NULL, 0},
{"vacuum", no_argument, 0, "try to remove all of the generated file/sockets", uwsgi_opt_true, &uwsgi.vacuum, 0},
{"file-write", required_argument, 0, "write the specified content to the specified file (syntax: file=value) before privileges drop", uwsgi_opt_add_string_list, &uwsgi.file_write_list, 0},
#ifdef __linux__
{"cgroup", required_argument, 0, "put the processes in the specified cgroup", uwsgi_opt_add_string_list, &uwsgi.cgroup, 0},
{"cgroup-opt", required_argument, 0, "set value in specified cgroup option", uwsgi_opt_add_string_list, &uwsgi.cgroup_opt, 0},
@@ -592,6 +617,10 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"zerg-server", required_argument, 0, "enable the zerg server on the specified UNIX socket", uwsgi_opt_set_str, &uwsgi.zerg_server, UWSGI_OPT_MASTER},
{"cron", required_argument, 0, "add a cron task", uwsgi_opt_add_cron, NULL, UWSGI_OPT_MASTER},
#ifdef UWSGI_SSL
{"legion-cron", required_argument, 0, "add a cron task runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron, NULL, UWSGI_OPT_MASTER},
{"cron-legion", required_argument, 0, "add a cron task runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron, NULL, UWSGI_OPT_MASTER},
#endif
{"loop", required_argument, 0, "select the uWSGI loop engine", uwsgi_opt_set_str, &uwsgi.loop, 0},
{"loop-list", no_argument, 0, "list enabled loop engines", uwsgi_opt_true, &uwsgi.loop_list, 0},
{"loops-list", no_argument, 0, "list enabled loop engines", uwsgi_opt_true, &uwsgi.loop_list, 0},
@@ -599,6 +628,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"attach-daemon", required_argument, 0, "attach a command/daemon to the master process (the command has to not go in background)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
{"smart-attach-daemon", required_argument, 0, "attach a command/daemon to the master process managed by a pidfile (the command has to daemonize)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
{"smart-attach-daemon2", required_argument, 0, "attach a command/daemon to the master process managed by a pidfile (the command has to NOT daemonize)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
{"daemons-honour-stdin", no_argument, 0, "do not change the stdin of external daemons to /dev/null", uwsgi_opt_true, &uwsgi.daemons_honour_stdin, UWSGI_OPT_MASTER},
{"plugins", required_argument, 0, "load uWSGI plugins", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
{"plugin", required_argument, 0, "load uWSGI plugins", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
{"plugins-dir", required_argument, 0, "add a directory to uWSGI plugin search path", uwsgi_opt_add_string_list, &uwsgi.plugins_dir, UWSGI_OPT_IMMEDIATE},
@@ -779,8 +809,12 @@ void config_magic_table_fill(char *filename, char **magic_table) {
char *section = uwsgi_get_last_char(filename, ':');
if (section) {
*section = 0;
if (section == filename) {
goto reuse;
}
}
// we have a special case for symlinks
if (uwsgi_is_link(filename)) {
if (filename[0] != '/') {
@@ -834,6 +868,7 @@ void config_magic_table_fill(char *filename, char **magic_table) {
if (uwsgi_get_last_char(magic_table['s'], '.'))
magic_table['n'] = uwsgi_concat2n(magic_table['s'], uwsgi_get_last_char(magic_table['s'], '.') - magic_table['s'], "", 0);
reuse:
if (section) {
magic_table['x'] = section+1;
*section = ':';
@@ -925,6 +960,10 @@ void gracefully_kill(int signum) {
}
void end_me(int signum) {
if (getpid() != masterpid && uwsgi.skip_atexit) {
_exit(UWSGI_END_CODE);
// never here
}
exit(UWSGI_END_CODE);
}
@@ -976,9 +1015,18 @@ void grace_them_all(int signum) {
if (uwsgi_instance_is_reloading || uwsgi_instance_is_dying)
return;
int i;
if (uwsgi.lazy) {
for (i = 1; i <= uwsgi.numproc; i++) {
uwsgi_curse(i, SIGHUP);
}
return;
}
uwsgi.status.gracefully_reloading = 1;
int i;
int waitpid_status;
@@ -1011,8 +1059,6 @@ void grace_them_all(int signum) {
}
}
else if (uwsgi.workers[i].pid > 0) {
if (uwsgi.lazy)
uwsgi.workers[i].destroy = 1;
uwsgi_curse(i, SIGHUP);
}
}
@@ -1027,6 +1073,9 @@ void grace_them_all(int signum) {
void uwsgi_nuclear_blast() {
// the Emperor (as an example) cannot nuke itself
if (uwsgi.disable_nuclear_blast) return;
if (!uwsgi.workers) {
reap_them_all(0);
}
@@ -1171,7 +1220,6 @@ void what_i_am_doing() {
}
pid_t masterpid;
int unconfigured_hook(struct wsgi_request *wsgi_req) {
uwsgi_log("-- unavailable modifier requested: %d --\n", wsgi_req->uh->modifier1);
@@ -1341,7 +1389,7 @@ void fixup_argv_and_environ(int argc, char **argv, char **environ) {
env_count++;
}
uwsgi.environ = uwsgi_malloc(sizeof(char *) * env_count);
uwsgi.environ = uwsgi_malloc(sizeof(char *) * (env_count+1));
for (i = 0; i < env_count; i++) {
uwsgi.environ[i] = strdup(environ[i]);
#ifdef UWSGI_DEBUG
@@ -1349,6 +1397,7 @@ void fixup_argv_and_environ(int argc, char **argv, char **environ) {
#endif
environ[i] = uwsgi.environ[i];
}
uwsgi.environ[env_count] = NULL;
#ifdef UWSGI_DEBUG
uwsgi_log("max space for custom process name = %d\n", uwsgi.max_procname);
@@ -1596,10 +1645,6 @@ int main(int argc, char *argv[], char *envp[]) {
int i;
#ifdef UNBIT
//struct uidsec_struct us;
#endif
struct utsname uuts;
// signal mask is inherited, and sme process manager could make a real mess...
@@ -1701,7 +1746,13 @@ int main(int argc, char *argv[], char *envp[]) {
// count/set the current reload status
uwsgi_setup_reload();
#ifdef __CYGWIN__
SYSTEM_INFO si;
GetSystemInfo(&si);
uwsgi.page_size = si.dwPageSize;
#else
uwsgi.page_size = getpagesize();
#endif
uwsgi.binary_path = uwsgi_get_binary_path(argv[0]);
// ok we can now safely play with argv and environ
@@ -1737,6 +1788,7 @@ int main(int argc, char *argv[], char *envp[]) {
// set a couple of 'static' magic vars
uwsgi.magic_table['v'] = uwsgi.cwd;
uwsgi.magic_table['h'] = uwsgi.hostname;
uwsgi.magic_table['V'] = UWSGI_VERSION;
// you can embed a ini file in the uWSGi binary with default options
#ifdef UWSGI_EMBED_CONFIG
@@ -1785,12 +1837,14 @@ int main(int argc, char *argv[], char *envp[]) {
// initial log setup (files and daemonization)
uwsgi_setup_log();
#ifndef __CYGWIN__
// enable never-swap mode
if (uwsgi.never_swap) {
if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
uwsgi_error("mlockall()");
}
}
#endif
if (uwsgi.flock2)
uwsgi_opt_flock(NULL, uwsgi.flock2, NULL);
@@ -2013,6 +2067,8 @@ int uwsgi_start(void *v_argv) {
}
#endif
uwsgi_file_write_do(uwsgi.file_write_list);
if (!uwsgi.master_as_root && !uwsgi.chown_socket) {
uwsgi_as_root();
}
@@ -2093,6 +2149,20 @@ int uwsgi_start(void *v_argv) {
// automatically fix options
sanitize_args();
if (uwsgi.requested_max_fd) {
uwsgi.rl.rlim_cur = uwsgi.requested_max_fd;
uwsgi.rl.rlim_max = uwsgi.requested_max_fd;
if (setrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
uwsgi_error("setrlimit()");
}
}
if (!getrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
uwsgi.max_fd = uwsgi.rl.rlim_cur;
uwsgi_log_initial("detected max file descriptor number: %lu\n", (unsigned long) uwsgi.max_fd);
}
// start the Emperor if needed
if (!uwsgi.early_emperor && uwsgi.emperor) {
uwsgi_emperor_start();
@@ -2117,19 +2187,6 @@ int uwsgi_start(void *v_argv) {
}
}
if (uwsgi.requested_max_fd) {
uwsgi.rl.rlim_cur = uwsgi.requested_max_fd;
uwsgi.rl.rlim_max = uwsgi.requested_max_fd;
if (setrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
uwsgi_error("setrlimit()");
}
}
if (!getrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
uwsgi.max_fd = uwsgi.rl.rlim_cur;
uwsgi_log_initial("detected max file descriptor number: %lu\n", (unsigned long) uwsgi.max_fd);
}
if (uwsgi.async > 1) {
if ((unsigned long) uwsgi.max_fd < (unsigned long) uwsgi.async) {
uwsgi_log("- your current max open files limit is %lu, this is lower than requested async cores !!! -\n", (unsigned long) uwsgi.max_fd);
@@ -2316,7 +2373,8 @@ int uwsgi_start(void *v_argv) {
!uwsgi.udp_socket &&
!uwsgi.emperor &&
!uwsgi.command_mode &&
!uwsgi.daemons_cnt
!uwsgi.daemons_cnt &&
!uwsgi.crons
#ifdef UWSGI_SSL
&& !uwsgi.legions
#endif
@@ -2379,7 +2437,14 @@ unsafe:
if (uwsgi.crons) {
struct uwsgi_cron *ucron = uwsgi.crons;
while (ucron) {
uwsgi_log("command \"%s\" registered as uWSGI-cron task\n", ucron->command);
#ifdef UWSGI_SSL
if (ucron->legion) {
uwsgi_log("[uwsgi-cron] command \"%s\" registered as cron task for legion \"%s\"\n", ucron->command, ucron->legion);
ucron = ucron->next;
continue;
}
#endif
uwsgi_log("[uwsgi-cron] command \"%s\" registered as cron task\n", ucron->command);
ucron = ucron->next;
}
}
@@ -2515,11 +2580,9 @@ next:
exit(0);
}
#ifdef UWSGI_MINTERPRETERS
if (!uwsgi.single_interpreter && uwsgi.numproc > 0) {
uwsgi_log("*** uWSGI is running in multiple interpreter mode ***\n");
}
#endif
// check for request plugins, and eventually print a warning
int rp_available = 0;
@@ -3104,6 +3167,18 @@ void uwsgi_init_all_apps() {
}
}
usl = uwsgi.exec_post_app;
while (usl) {
uwsgi_log("running \"%s\" (post app)...\n", usl->value);
int ret = uwsgi_run_command_and_wait(NULL, usl->value);
if (ret != 0) {
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
exit(1);
}
usl = usl->next;
}
}
void uwsgi_init_worker_mount_apps() {
@@ -3146,6 +3221,67 @@ void uwsgi_opt_true(char *opt, char *value, void *key) {
}
}
void uwsgi_opt_set_immediate_gid(char *opt, char *value, void *none) {
gid_t gid = atoi(value);
if (gid == 0) {
struct group *ugroup = getgrnam(value);
if (ugroup)
gid = ugroup->gr_gid;
}
if (gid <= 0) {
uwsgi_log("uwsgi_opt_set_immediate_gid(): invalid gid %d\n", (int) gid);
exit(1);
}
if (setgid(gid)) {
uwsgi_error("uwsgi_opt_set_immediate_gid()/setgid()");
exit(1);
}
if (setgroups(0, NULL)) {
uwsgi_error("uwsgi_opt_set_immediate_gid()/setgroups()");
exit(1);
}
gid = getgid();
if (!gid) {
exit(1);
}
uwsgi_log("immediate gid: %d\n", (int) gid);
}
void uwsgi_opt_set_immediate_uid(char *opt, char *value, void *none) {
uid_t uid = atoi(value);
if (uid == 0) {
struct passwd *upasswd = getpwnam(value);
if (upasswd)
uid = upasswd->pw_uid;
}
if (uid <= 0) {
uwsgi_log("uwsgi_opt_set_immediate_uid(): invalid uid %d\n", uid);
exit(1);
}
if (setuid(uid)) {
uwsgi_error("uwsgi_opt_set_immediate_uid()/setuid()");
exit(1);
}
uid = getuid();
if (!uid) {
exit(1);
}
uwsgi_log("immediate uid: %d\n", (int) uid);
}
void uwsgi_opt_safe_fd(char *opt, char *value, void *foobar) {
int fd = atoi(value);
if (fd < 0) {
uwsgi_log("invalid file descriptor: %d\n", fd);
exit(1);
}
uwsgi_add_safe_fd(fd);
}
void uwsgi_opt_set_int(char *opt, char *value, void *key) {
int *ptr = (int *) key;
if (value) {
@@ -3695,12 +3831,10 @@ void uwsgi_opt_deprecated(char *opt, char *value, void *message) {
void uwsgi_opt_load(char *opt, char *filename, void *none) {
#ifdef UWSGI_INI
if (uwsgi_endswith(filename, ".ini")) {
uwsgi_opt_load_ini(opt, filename, none);
return;
}
#endif
#ifdef UWSGI_XML
if (uwsgi_endswith(filename, ".xml")) {
uwsgi_opt_load_xml(opt, filename, none);
@@ -3727,6 +3861,9 @@ void uwsgi_opt_load(char *opt, char *filename, void *none) {
return;
}
#endif
// fallback to pluggable system
uwsgi_opt_load_config(opt, filename, none);
}
void uwsgi_opt_logic(char *opt, char *arg, void *func) {
@@ -3748,12 +3885,25 @@ void uwsgi_opt_logic(char *opt, char *arg, void *func) {
void uwsgi_opt_noop(char *opt, char *foo, void *bar) {
}
#ifdef UWSGI_INI
void uwsgi_opt_load_ini(char *opt, char *filename, void *none) {
config_magic_table_fill(filename, uwsgi.magic_table);
uwsgi_ini_config(filename, uwsgi.magic_table);
}
#endif
void uwsgi_opt_load_config(char *opt, char *filename, void *none) {
struct uwsgi_configurator *uc = uwsgi.configurators;
while(uc) {
if (uwsgi_endswith(filename, uc->name)) {
config_magic_table_fill(filename, uwsgi.magic_table);
uc->func(filename, uwsgi.magic_table);
return;
}
uc = uc->next;
}
uwsgi_log("unable to load configuration from %s\n", filename);
exit(1);
}
#ifdef UWSGI_XML
void uwsgi_opt_load_xml(char *opt, char *filename, void *none) {
@@ -3769,13 +3919,6 @@ void uwsgi_opt_load_yml(char *opt, char *filename, void *none) {
}
#endif
#ifdef UWSGI_SQLITE3
void uwsgi_opt_load_sqlite3(char *opt, char *filename, void *none) {
config_magic_table_fill(filename, uwsgi.magic_table);
uwsgi_sqlite3_config(filename, uwsgi.magic_table);
}
#endif
#ifdef UWSGI_JSON
void uwsgi_opt_load_json(char *opt, char *filename, void *none) {
config_magic_table_fill(filename, uwsgi.magic_table);
@@ -3783,12 +3926,6 @@ void uwsgi_opt_load_json(char *opt, char *filename, void *none) {
}
#endif
#ifdef UWSGI_LDAP
void uwsgi_opt_load_ldap(char *opt, char *url, void *none) {
uwsgi_ldap_config(url);
}
#endif
void uwsgi_opt_add_custom_option(char *opt, char *value, void *none) {
struct uwsgi_custom_option *uco = uwsgi.custom_options, *old_uco;
+51 -2
View File
@@ -12,6 +12,36 @@ int uwsgi_response_add_content_length(struct wsgi_request *wsgi_req, uint64_t cl
return uwsgi_response_add_header(wsgi_req, "Content-Length", 14, buf, ret);
}
int uwsgi_response_add_expires(struct wsgi_request *wsgi_req, uint64_t t) {
// 30+1
char expires[31];
int len = uwsgi_http_date((time_t) t, expires);
if (!len) {
wsgi_req->write_errors++;
return -1;
}
return uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, len);
}
int uwsgi_response_add_content_range(struct wsgi_request *wsgi_req, uint64_t start, uint64_t end, uint64_t cl) {
char buf[6+(sizeof(UMAX64_STR)*3)+4];
if (end == 0) {
end = cl-1;
}
int ret = snprintf(buf, 6+(sizeof(UMAX64_STR)*3)+4, "bytes %llu-%llu/%llu", (unsigned long long) start, (unsigned long long) end, (unsigned long long) cl);
if (ret <= 0 || ret > (int) (6+(sizeof(UMAX64_STR)*3)+4)) {
wsgi_req->write_errors++;
return -1;
}
return uwsgi_response_add_header(wsgi_req, "Content-Range", 13, buf, ret);
}
int uwsgi_response_prepare_headers_int(struct wsgi_request *wsgi_req, int status) {
char status_str[11];
uwsgi_num2str2(status, status_str);
return uwsgi_response_prepare_headers(wsgi_req, status_str, 3);
}
// status could be NNN or NNN message
int uwsgi_response_prepare_headers(struct wsgi_request *wsgi_req, char *status, uint16_t status_len) {
@@ -141,11 +171,13 @@ int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
return UWSGI_OK;
}
// this is the function called by all request plugins to send chunks to the client
int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {
if (wsgi_req->write_errors) return -1;
if (!wsgi_req->headers_sent) {
// do not commit headers until a response_buffer is available (take in account flushing)
if ((wsgi_req->flush || !wsgi_req->response_buffer) && !wsgi_req->headers_sent) {
int ret = uwsgi_response_write_headers_do(wsgi_req);
if (ret == UWSGI_OK) goto sendbody;
if (ret == UWSGI_AGAIN) return UWSGI_AGAIN;
@@ -156,6 +188,15 @@ int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_
sendbody:
if (len == 0) return UWSGI_OK;
if (wsgi_req->response_buffer) {
if (uwsgi_buffer_append(wsgi_req->response_buffer, buf, len)) {
wsgi_req->write_errors++;
return -1;
}
if (!wsgi_req->flush)
return UWSGI_OK;
}
for(;;) {
int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
@@ -191,7 +232,10 @@ int uwsgi_response_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t pos
if (fd == wsgi_req->sendfile_fd) can_close = 0;
if (wsgi_req->write_errors) return -1;
if (wsgi_req->write_errors) {
if (can_close) close(fd);
return -1;
}
if (!wsgi_req->headers_sent) {
int ret = uwsgi_response_write_headers_do(wsgi_req);
@@ -212,6 +256,10 @@ sendfile:
if (can_close) close(fd);
return -1;
}
if (pos >= (size_t)st.st_size) {
if (can_close) close(fd);
return UWSGI_OK;
}
len = st.st_size;
}
@@ -263,6 +311,7 @@ sendfile:
if (ret == 0) {
uwsgi_log("uwsgi_response_sendfile_do() TIMEOUT !!!\n");
wsgi_req->write_errors++;
if (can_close) close(fd);
return -1;
}
}
+32
View File
@@ -1,5 +1,37 @@
#include <uwsgi.h>
static char gzheader[10] = { 0x1f, 0x8b, Z_DEFLATED, 0, 0, 0, 0, 0, 0, 3 };
struct uwsgi_buffer *uwsgi_gzip(char *buf, size_t len) {
z_stream z;
struct uwsgi_buffer *ub = NULL;
uint32_t gzip_crc32 = 0;
char *gzipped = NULL;
char *gzipped0 = NULL;
size_t dlen = 0;
size_t dlen0 = 0;
uwsgi_crc32(&gzip_crc32, NULL, 0);
if (uwsgi_deflate_init(&z, NULL, 0)) return NULL;
uwsgi_crc32(&gzip_crc32, buf, len);
gzipped = uwsgi_deflate(&z, buf, len, &dlen);
if (!gzipped) goto end;
gzipped0 = uwsgi_deflate(&z, NULL, 0, &dlen0);
if (!gzipped0) goto end;
ub = uwsgi_buffer_new(10 + dlen + dlen0 + 8);
if (uwsgi_buffer_append(ub, gzheader, 10)) goto end;
if (uwsgi_buffer_append(ub, gzipped, dlen)) goto end;
if (uwsgi_buffer_append(ub, gzipped0, dlen0)) goto end;
if (uwsgi_buffer_u32le(ub, gzip_crc32)) goto end;
if (uwsgi_buffer_u32le(ub, len)) goto end;
end:
if (gzipped) free(gzipped);
if (gzipped0) free(gzipped0);
deflateEnd(&z);
return ub;
}
int uwsgi_deflate_init(z_stream *z, char *dict, size_t dict_len) {
z->zalloc = Z_NULL;
+9
View File
@@ -0,0 +1,9 @@
config = {}
config['immediate-uid'] = 'roberto'
config['immediate-gid'] = 'roberto'
config['http-socket'] = ':9090'
config['env'] = { 'FOO=bar', 'TEST=topogigio' }
config['module'] = 'werkzeug.testapp:test_app'
return config
+8
View File
@@ -0,0 +1,8 @@
config = {}
config[1] = { ['http-socket']=':9090' }
config[2] = { ['env']='FOO=bar' }
config[3] = { ['env']='TEST=topogigio' }
config[4] = { ['module']='werkzeug.testapp:test_app' }
return config
-1356
View File
File diff suppressed because it is too large Load Diff
-3
View File
@@ -1,3 +0,0 @@
ngx_addon_name=ngx_http_uwsgi_module
HTTP_MODULES="$HTTP_MODULES ngx_http_uwsgi_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_uwsgi_module.c"
File diff suppressed because it is too large Load Diff
-16
View File
@@ -1,16 +0,0 @@
uwsgi_param QUERY_STRING $query_string;
uwsgi_param REQUEST_METHOD $request_method;
uwsgi_param CONTENT_TYPE $content_type;
uwsgi_param CONTENT_LENGTH $content_length;
uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_ADDR $server_addr;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_NAME $server_name;
+9 -5
View File
@@ -40,7 +40,7 @@ static void cache_simple_command(char *key, uint16_t keylen, char *val, uint16_t
if (vallen > 0) {
if (!uwsgi_strncmp(key, keylen, "key", 3)) {
uint64_t vallen = 0;
char *value = uwsgi_cache_magic_get(val, vallen, &vallen, NULL);
char *value = uwsgi_cache_magic_get(val, vallen, &vallen, NULL, NULL);
if (value) {
uwsgi_response_write_body_do(wsgi_req, value, vallen);
free(value);
@@ -49,7 +49,7 @@ static void cache_simple_command(char *key, uint16_t keylen, char *val, uint16_t
}
else if (!uwsgi_strncmp(key, keylen, "get", 3)) {
uint64_t vallen = 0;
char *value = uwsgi_cache_magic_get(val, vallen, &vallen, NULL);
char *value = uwsgi_cache_magic_get(val, vallen, &vallen, NULL, NULL);
if (value) {
uwsgi_response_write_body_do(wsgi_req, value, vallen);
free(value);
@@ -77,8 +77,9 @@ static void manage_magic_context(struct wsgi_request *wsgi_req, struct uwsgi_cac
// cache get
if (!uwsgi_strncmp(ucmc->cmd, ucmc->cmd_len, "get", 3)) {
uint64_t vallen = 0;
uint64_t expires = 0;
uwsgi_rlock(uc->lock);
char *value = uwsgi_cache_get2(uc, ucmc->key, ucmc->key_len, &vallen);
char *value = uwsgi_cache_get3(uc, ucmc->key, ucmc->key_len, &vallen, &expires);
if (!value) {
uwsgi_rwunlock(uc->lock);
return;
@@ -88,6 +89,9 @@ static void manage_magic_context(struct wsgi_request *wsgi_req, struct uwsgi_cac
ub->pos = 4;
if (uwsgi_buffer_append_keyval(ub, "status", 6, "ok", 2)) goto error;
if (uwsgi_buffer_append_keynum(ub, "size", 4, vallen)) goto error;
if (expires) {
if (uwsgi_buffer_append_keynum(ub, "expires", 7, expires)) goto error;
}
if (uwsgi_buffer_set_uh(ub, 111, 17)) goto error;
if (uwsgi_buffer_append(ub, value, vallen)) goto error;
// unlock !!!
@@ -205,7 +209,7 @@ static int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
case 0:
// get
if (wsgi_req->uh->pktsize > 0) {
value = uwsgi_cache_magic_get(wsgi_req->buffer, wsgi_req->uh->pktsize, &vallen, NULL);
value = uwsgi_cache_magic_get(wsgi_req->buffer, wsgi_req->uh->pktsize, &vallen, NULL, NULL);
if (value) {
wsgi_req->uh->pktsize = vallen;
if (uwsgi_response_write_body_do(wsgi_req, (char *)&wsgi_req->uh, 4)) { free(value) ; return -1;}
@@ -242,7 +246,7 @@ static int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
case 5:
// get (uwsgi + stream)
if (wsgi_req->uh->pktsize > 0) {
value = uwsgi_cache_magic_get(wsgi_req->buffer, wsgi_req->uh->pktsize, &vallen, NULL);
value = uwsgi_cache_magic_get(wsgi_req->buffer, wsgi_req->uh->pktsize, &vallen, NULL, NULL);
if (value) {
wsgi_req->uh->pktsize = 0;
wsgi_req->uh->modifier2 = 1;
+103 -14
View File
@@ -9,9 +9,10 @@
extern struct uwsgi_server uwsgi;
struct carbon_server_list {
char *value; // server address
int healthy;
int errors;
char *hostname;
char *port;
struct carbon_server_list *next;
};
@@ -33,6 +34,11 @@ struct uwsgi_carbon {
char *root_node;
char *hostname_dot_replacement;
char *hostname;
int resolve_hostname;
char *idle_avg;
int push_avg;
int zero_avg;
uint64_t last_requests;
struct uwsgi_stats_pusher *pusher;
} u_carbon;
@@ -46,6 +52,9 @@ static struct uwsgi_option carbon_options[] = {
{"carbon-retry-delay", required_argument, 0, "set connection retry delay in seconds (default 7)", uwsgi_opt_set_int, &u_carbon.retry_delay, 0},
{"carbon-root", required_argument, 0, "set carbon metrics root node (default 'uwsgi')", uwsgi_opt_set_str, &u_carbon.root_node, 0},
{"carbon-hostname-dots", required_argument, 0, "set char to use as a replacement for dots in hostname (dots are not replaced by default)", uwsgi_opt_set_str, &u_carbon.hostname_dot_replacement, 0},
{"carbon-name-resolve", no_argument, 0, "allow using hostname as carbon server address (default disabled)", uwsgi_opt_true, &u_carbon.resolve_hostname, 0},
{"carbon-resolve-names", no_argument, 0, "allow using hostname as carbon server address (default disabled)", uwsgi_opt_true, &u_carbon.resolve_hostname, 0},
{"carbon-idle-avg", required_argument, 0, "average values source during idle period (no requests), can be \"last\", \"zero\", \"none\" (default is last)", uwsgi_opt_set_str, &u_carbon.idle_avg, 0},
{0, 0, 0, 0, 0, 0, 0},
};
@@ -59,15 +68,37 @@ static void carbon_post_init() {
while(usl) {
struct carbon_server_list *u_server = uwsgi_calloc(sizeof(struct carbon_server_list));
u_server->value = usl->value;
u_server->healthy = 1;
u_server->errors = 0;
char *p = strtok(usl->value, ":");
while (p) {
if (!u_server->hostname) {
u_server->hostname = uwsgi_str(p);
}
else if (!u_server->port) {
u_server->port = uwsgi_str(p);
}
else
break;
p = strtok(NULL, ":");
}
if (!u_server->hostname || !u_server->port) {
uwsgi_log("[carbon] invalid carbon server address (%s)\n", usl->value);
usl = usl->next;
if (u_server->hostname) free(u_server->hostname);
if (u_server->port) free(u_server->port);
free(u_server);
continue;
}
if (u_carbon.servers_data) {
u_server->next = u_carbon.servers_data;
}
u_carbon.servers_data = u_server;
uwsgi_log("[carbon] added server %s\n", usl->value);
uwsgi_log("[carbon] added server %s:%s\n", u_server->hostname, u_server->port);
usl = usl->next;
}
@@ -80,7 +111,7 @@ static void carbon_post_init() {
if (u_carbon.timeout < 1) u_carbon.timeout = 3;
if (u_carbon.max_retries <= 0) u_carbon.max_retries = 1;
if (u_carbon.retry_delay <= 0) u_carbon.retry_delay = 7;
if (!u_carbon.id) {
if (!u_carbon.id) {
u_carbon.id = uwsgi_str(uwsgi.sockets->name);
for(i=0;i<(int)strlen(u_carbon.id);i++) {
@@ -95,6 +126,22 @@ static void carbon_post_init() {
}
}
u_carbon.push_avg = 1;
u_carbon.zero_avg = 0;
if (!u_carbon.idle_avg) {
u_carbon.idle_avg = "last";
}
else if (!strcmp(u_carbon.idle_avg, "zero")) {
u_carbon.zero_avg = 1;
}
else if (!strcmp(u_carbon.idle_avg, "none")) {
u_carbon.push_avg = 0;
}
else if (strcmp(u_carbon.idle_avg, "last")) {
uwsgi_log("[carbon] invalid value for carbon-idle-avg: \"%s\"\n", u_carbon.idle_avg);
exit(1);
}
if (!u_carbon.last_busyness_values) {
u_carbon.last_busyness_values = uwsgi_calloc(sizeof(unsigned long long) * uwsgi.numproc);
}
@@ -145,6 +192,8 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
int i;
int fd;
int wok;
char *ip;
char *carbon_address = NULL;
for (i = 0; i < uwsgi.numproc; i++) {
u_carbon.current_busyness_values[i] = uwsgi.workers[i+1].running_time - u_carbon.last_busyness_values[i];
@@ -157,31 +206,44 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
if (retry_cycle && usl->healthy)
// skip healthy servers during retry cycle
goto nxt;
if (retry_cycle && usl->healthy == 0)
uwsgi_log("[carbon] Retrying failed server at %s (%d)\n", usl->value, usl->errors);
uwsgi_log("[carbon] Retrying failed server at %s (%d)\n", usl->hostname, usl->errors);
if (!retry_cycle) {
usl->healthy = 1;
usl->errors = 0;
}
fd = uwsgi_connect(usl->value, u_carbon.timeout, 0);
if (u_carbon.resolve_hostname) {
ip = uwsgi_resolve_ip(usl->hostname);
if (!ip) {
uwsgi_log("[carbon] Could not resolve hostname %s\n", usl->hostname);
goto nxt;
}
carbon_address = uwsgi_concat3(ip, ":", usl->port);
}
else {
carbon_address = uwsgi_concat3(usl->hostname, ":", usl->port);
}
fd = uwsgi_connect(carbon_address, u_carbon.timeout, 0);
if (fd < 0) {
uwsgi_log("[carbon] Could not connect to carbon server at %s\n", usl->value);
uwsgi_log("[carbon] Could not connect to carbon server at %s\n", carbon_address);
if (usl->errors < u_carbon.max_retries) {
u_carbon.need_retry = 1;
u_carbon.next_retry = uwsgi_now() + u_carbon.retry_delay;
} else {
uwsgi_log("[carbon] Maximum number of retries for %s (%d)\n",
usl->value, u_carbon.max_retries);
carbon_address, u_carbon.max_retries);
usl->healthy = 0;
usl->errors = 0;
}
usl->healthy = 0;
usl->errors++;
free(carbon_address);
goto nxt;
}
free(carbon_address);
// put the socket in non-blocking mode
uwsgi_socket_nb(fd);
@@ -196,6 +258,8 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
unsigned long long worker_busyness = 0;
unsigned long long total_harakiri = 0;
int do_avg_push;
wok = carbon_write(fd, "%s%s.%s.requests %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) uwsgi.workers[0].requests, (unsigned long long) now);
if (!wok) goto clear;
@@ -246,8 +310,19 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
if (!wok) goto clear;
}
wok = carbon_write(fd, "%s%s.%s.worker%d.avg_rt %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) avg_rt, (unsigned long long) now);
if (!wok) goto clear;
do_avg_push = 1;
if (!u_carbon.last_requests || u_carbon.last_requests == uwsgi.workers[0].requests) {
if (!u_carbon.push_avg) {
do_avg_push = 0;
}
else if (u_carbon.zero_avg) {
avg_rt = 0;
}
}
if (do_avg_push) {
wok = carbon_write(fd, "%s%s.%s.worker%d.avg_rt %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) avg_rt, (unsigned long long) now);
if (!wok) goto clear;
}
wok = carbon_write(fd, "%s%s.%s.worker%d.tx %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].tx, (unsigned long long) now);
if (!wok) goto clear;
@@ -268,8 +343,20 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
if (!wok) goto clear;
}
wok = carbon_write(fd, "%s%s.%s.avg_rt %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) (active_workers ? total_avg_rt / active_workers : 0), (unsigned long long) now);
if (!wok) goto clear;
do_avg_push = 1;
uint64_t c_total_avg_rt = (active_workers ? total_avg_rt / active_workers : 0);
if (!u_carbon.last_requests || u_carbon.last_requests == uwsgi.workers[0].requests) {
if (!u_carbon.push_avg) {
do_avg_push = 0;
}
else if (u_carbon.zero_avg) {
c_total_avg_rt = 0;
}
}
if (do_avg_push) {
wok = carbon_write(fd, "%s%s.%s.avg_rt %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) c_total_avg_rt, (unsigned long long) now);
if (!wok) goto clear;
}
wok = carbon_write(fd, "%s%s.%s.tx %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) total_tx, (unsigned long long) now);
if (!wok) goto clear;
@@ -297,6 +384,8 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
usl->healthy = 1;
usl->errors = 0;
u_carbon.last_requests = uwsgi.workers[0].requests;
clear:
close(fd);
nxt:
+109 -43
View File
@@ -18,7 +18,7 @@ struct uwsgi_cgi {
int path_info;
} uc ;
void uwsgi_opt_add_cgi(char *opt, char *value, void *foobar) {
static void uwsgi_opt_add_cgi(char *opt, char *value, void *foobar) {
char *val = strchr(value, '=');
if (!val) {
@@ -30,7 +30,7 @@ void uwsgi_opt_add_cgi(char *opt, char *value, void *foobar) {
}
void uwsgi_opt_add_cgi_maphelper(char *opt, char *value, void *foobar) {
static void uwsgi_opt_add_cgi_maphelper(char *opt, char *value, void *foobar) {
char *val = strchr(value, '=');
if (!val) {
uwsgi_log("invalid CGI helper syntax, must be ext=command\n");
@@ -66,7 +66,7 @@ struct uwsgi_option uwsgi_cgi_options[] = {
};
void uwsgi_cgi_apps() {
static void uwsgi_cgi_apps() {
struct uwsgi_dyn_dict *udd = uc.mountpoint;
struct stat st;
@@ -123,7 +123,7 @@ void uwsgi_cgi_apps() {
}
int uwsgi_cgi_init(){
static int uwsgi_cgi_init(){
void (*cgi_sym)(void);
@@ -161,7 +161,7 @@ int uwsgi_cgi_init(){
}
char *uwsgi_cgi_get_helper(char *filename) {
static char *uwsgi_cgi_get_helper(char *filename) {
struct uwsgi_dyn_dict *helpers = uc.helpers;
size_t len = strlen(filename);
@@ -179,7 +179,7 @@ char *uwsgi_cgi_get_helper(char *filename) {
}
int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len) {
static int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len) {
size_t i;
char *key = buf, *value = NULL;
@@ -266,7 +266,7 @@ send_body:
return 0;
}
char *uwsgi_cgi_get_docroot(char *path_info, uint16_t path_info_len, int *need_free, int *is_a_file, int *discard_base, char **script_name) {
static char *uwsgi_cgi_get_docroot(char *path_info, uint16_t path_info_len, int *need_free, int *is_a_file, int *discard_base, char **script_name) {
struct uwsgi_dyn_dict *udd = uc.mountpoint, *choosen_udd = NULL;
int best_found = 0;
@@ -323,7 +323,7 @@ char *uwsgi_cgi_get_docroot(char *path_info, uint16_t path_info_len, int *need_f
return path;
}
int uwsgi_cgi_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot, size_t docroot_len, int discard_base, char **path_info) {
static int uwsgi_cgi_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot, size_t docroot_len, int discard_base, char **path_info) {
// and now start walking...
uint16_t i;
@@ -380,18 +380,12 @@ int uwsgi_cgi_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot
}
int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
static int uwsgi_cgi_run(struct wsgi_request *, char *, size_t, char *, char *, char *, char *, int, int);
static int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
int i;
pid_t cgi_pid;
int waitpid_status;
char **argv;
int nargs = 0;
char full_path[PATH_MAX];
char tmp_path[PATH_MAX];
int cgi_pipe[2];
int post_pipe[2];
ssize_t len;
struct stat cgi_stat;
int need_free = 0;
int is_a_file = 0;
@@ -399,7 +393,6 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
size_t docroot_len = 0;
size_t full_path_len = 0;
char *helper = NULL;
char *command = NULL;
char *path_info = NULL;
char *script_name = NULL;
@@ -533,11 +526,8 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
return UWSGI_OK;
}
if (is_a_file) {
command = docroot;
}
else {
command = full_path;
// get the helper
if (!is_a_file) {
helper = uwsgi_cgi_get_helper(full_path);
if (helper == NULL) {
@@ -551,28 +541,43 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
}
}
int ret = uwsgi_cgi_run(wsgi_req, docroot, docroot_len, full_path, helper, path_info, script_name, is_a_file, discard_base);
if (need_free) free(docroot);
return ret;
}
static int uwsgi_cgi_run(struct wsgi_request *wsgi_req, char *docroot, size_t docroot_len, char *full_path, char *helper, char *path_info, char *script_name, int is_a_file, int discard_base) {
int cgi_pipe[2];
int post_pipe[2];
int nargs = 0;
int waitpid_status;
ssize_t len;
int i;
char **argv;
char *command = full_path;
if (is_a_file) {
command = docroot;
}
if (pipe(cgi_pipe)) {
if (need_free)
free(docroot);
uwsgi_error("pipe()");
uwsgi_error("uwsgi_cgi_run()/pipe()");
return UWSGI_OK;
}
if (pipe(post_pipe)) {
if (need_free)
free(docroot);
close(cgi_pipe[0]);
close(cgi_pipe[1]);
uwsgi_error("pipe()");
uwsgi_error("uwsgi_cgi_run()/pipe()");
return UWSGI_OK;
}
cgi_pid = fork();
pid_t cgi_pid = fork();
if (cgi_pid < 0) {
uwsgi_error("fork()");
if (need_free)
free(docroot);
uwsgi_error("uwsgi_cgi_run()/fork()");
close(cgi_pipe[0]);
close(cgi_pipe[1]);
close(post_pipe[0]);
@@ -582,9 +587,6 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
if (cgi_pid > 0) {
if (need_free)
free(docroot);
close(cgi_pipe[1]);
close(post_pipe[0]);
@@ -795,7 +797,7 @@ clear2:
}
*base = '/';
}
else {
else if (docroot_len > 0) {
if (chdir(docroot)) {
uwsgi_error("chdir()");
}
@@ -837,9 +839,8 @@ clear2:
escape_shell_arg(arg_copy, arg_copy_len, argv[i]);
i++;
p = strtok(NULL, "+");
}
}
else {
}
free(qs);
}
}
@@ -864,7 +865,7 @@ clear2:
}
if (execvp(argv[0], argv)) {
uwsgi_error("execvp()");
uwsgi_error("uwsgi_cgi_run()/execvp()");
}
// never here
@@ -872,11 +873,73 @@ clear2:
}
void uwsgi_cgi_after_request(struct wsgi_request *wsgi_req) {
static void uwsgi_cgi_after_request(struct wsgi_request *wsgi_req) {
log_request(wsgi_req);
}
#ifdef UWSGI_ROUTING
static int uwsgi_routing_func_cgi(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub_command = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub_command) return UWSGI_ROUTE_BREAK;
struct uwsgi_buffer *ub_helper = NULL;
if (ur->data2_len) {
ub_helper = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data2, ur->data2_len);
if (!ub_helper) {
uwsgi_buffer_destroy(ub_command);
return UWSGI_ROUTE_BREAK;
}
}
else {
if (!uwsgi_is_file(ub_command->buf)) {
uwsgi_404(wsgi_req);
uwsgi_buffer_destroy(ub_command);
return UWSGI_ROUTE_BREAK;
}
if (access(ub_command->buf, X_OK)) {
uwsgi_403(wsgi_req);
uwsgi_buffer_destroy(ub_command);
return UWSGI_ROUTE_BREAK;
}
}
// we need a NULL suffix-ed copy of the docroot
char *docroot = uwsgi_concat2n(wsgi_req->document_root, wsgi_req->document_root_len, "", 0);
uwsgi_cgi_run(wsgi_req, wsgi_req->document_root, wsgi_req->document_root_len, ub_command->buf, ub_helper ? ub_helper->buf : NULL, NULL, NULL, 0, 0 );
free(docroot);
uwsgi_buffer_destroy(ub_command);
if (ub_helper) uwsgi_buffer_destroy(ub_helper);
return UWSGI_ROUTE_BREAK;
}
static int uwsgi_router_cgi_helper(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_cgi;
char *space = strchr(args, ' ');
if (!space) {
uwsgi_log("invalid cgihelper syntax, must be \"cgihelper:helper command\"\n");
return -1;
}
*space = 0;
ur->data = space+1;
ur->data_len = strlen(space+1);
ur->data2 = args;
ur->data2_len = strlen(args);
return 0;
}
static int uwsgi_router_cgi(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_cgi;
ur->data = args;
ur->data_len = strlen(args);
return 0;
}
static void uwsgi_cgi_register_router() {
uwsgi_register_router("cgi", uwsgi_router_cgi);
uwsgi_register_router("cgihelper", uwsgi_router_cgi_helper);
}
#endif
struct uwsgi_plugin cgi_plugin = {
@@ -887,5 +950,8 @@ struct uwsgi_plugin cgi_plugin = {
.options = uwsgi_cgi_options,
.request = uwsgi_cgi_request,
.after_request = uwsgi_cgi_after_request,
#ifdef UWSGI_ROUTING
.on_load = uwsgi_cgi_register_router,
#endif
};
+4 -3
View File
@@ -701,7 +701,8 @@ void uwsgi_corerouter_loop(int id, void *data) {
if (ucr->use_cache) {
ucr->cache = uwsgi_cache_by_name(ucr->use_cache);
if (!ucr->cache) {
uwsgi_log("unable to find cache \"%s\"\n", ucr->use_cache);
uwsgi_log("!!! unable to find cache \"%s\" !!!\n", ucr->use_cache);
exit(1);
}
ucr->mapper = uwsgi_cr_map_use_cache;
}
@@ -899,7 +900,7 @@ int uwsgi_corerouter_init(struct uwsgi_corerouter *ucr) {
if (ucr->has_sockets) {
if (ucr->use_cache && !uwsgi.cache_max_items) {
if (ucr->use_cache && !uwsgi.caches) {
uwsgi_log("you need to create a uwsgi cache to use the %s (add --cache <n>)\n", ucr->name);
exit(1);
}
@@ -945,7 +946,7 @@ void corerouter_send_stats(struct uwsgi_corerouter *ucr) {
int client_fd = accept(ucr->cr_stats_server, (struct sockaddr *) &client_src, &client_src_len);
if (client_fd < 0) {
uwsgi_error("accept()");
uwsgi_error("corerouter_send_stats()/accept()");
return;
}
+1 -1
View File
@@ -173,7 +173,7 @@ void uwsgi_corerouter_manage_subscription(struct uwsgi_corerouter *ucr, int id,
continue;
if (!strcmp(ushared->gateways[i].name, ucr->name)) {
if (send(ushared->gateways[i].internal_subscription_pipe[0], bbuf, len, 0) != len) {
uwsgi_error("send()");
uwsgi_error("uwsgi_corerouter_manage_subscription()/send()");
}
}
}
+1 -1
View File
@@ -171,7 +171,7 @@ end:
}
XS(XS_coroae_sighandler) {
int sigfd = (int) XSANY.any_ptr;
int sigfd = (long) XSANY.any_ptr;
uwsgi_receive_signal(sigfd, "worker", uwsgi.mywid);
}
+6 -4
View File
@@ -1,4 +1,4 @@
#include "../../uwsgi.h"
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
@@ -13,8 +13,9 @@ class FakeClass {
void FakeClass::hello_world(struct wsgi_request *wsgi_req) {
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, (char *) "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n", 44);
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, foobar, foobar_len);
uwsgi_response_prepare_headers(wsgi_req, (char *)"200 OK", 6);
uwsgi_response_add_content_type(wsgi_req, (char *)"text/html", 9);
uwsgi_response_write_body_do(wsgi_req, foobar, foobar_len);
}
extern "C" int uwsgi_cplusplus_init(){
@@ -27,7 +28,7 @@ extern "C" int uwsgi_cplusplus_request(struct wsgi_request *wsgi_req) {
FakeClass *fc;
// empty request ?
if (!wsgi_req->uh.pktsize) {
if (!wsgi_req->uh->pktsize) {
uwsgi_log( "Invalid request. skip.\n");
goto clear;
}
@@ -55,6 +56,7 @@ clear:
extern "C" void uwsgi_cplusplus_after_request(struct wsgi_request *wsgi_req) {
// call log_request(wsgi_req) if you want a standard logline
uwsgi_log("logging c++ request\n");
}
+1 -1
View File
@@ -1,4 +1,4 @@
#include "../../uwsgi.h"
#include <uwsgi.h>
int uwsgi_cplusplus_init(void);
+58
View File
@@ -0,0 +1,58 @@
#include <uwsgi.h>
#include <curl/curl.h>
extern struct uwsgi_server uwsgi;
static void curl_cron_func(struct uwsgi_cron *uc, time_t now) {
CURL *curl = curl_easy_init();
// ARGH !!!
if (!curl) return;
curl_easy_setopt(curl, CURLOPT_URL, uc->command);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
// use 1 minute as the cron resolution
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60);
uwsgi_log("[uwsgi-curl-cron] requesting %s\n", uc->command);
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
uwsgi_log("[uwsgi-curl-cron] curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
}
curl_easy_cleanup(curl);
}
static void uwsgi_opt_add_cron_curl(char *opt, char *value, void *foobar) {
struct uwsgi_cron *uc = uwsgi_cron_add(value);
uc->func = curl_cron_func;
}
#ifdef UWSGI_SSL
static void uwsgi_opt_add_legion_cron_curl(char *opt, char *value, void *foobar) {
char *space = strchr(value, ' ');
if (!space) {
uwsgi_log("invalid %s syntax, must be prefixed with a legion name\n", opt);
exit(1);
}
char *legion = uwsgi_concat2n(value, space-value, "", 0);
struct uwsgi_cron *uc = uwsgi_cron_add(space+1);
uc->legion = legion;
uc->func = curl_cron_func;
}
#endif
static struct uwsgi_option curl_cron_options[] = {
{"curl-cron", required_argument, 0, "add a cron task invoking the specified url via CURL", uwsgi_opt_add_cron_curl, NULL, UWSGI_OPT_MASTER},
{"cron-curl", required_argument, 0, "add a cron task invoking the specified url via CURL", uwsgi_opt_add_cron_curl, NULL, UWSGI_OPT_MASTER},
#ifdef UWSGI_SSL
{"legion-curl-cron", required_argument, 0, "add a cron task invoking the specified url via CURL runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron_curl, NULL, UWSGI_OPT_MASTER},
{"legion-cron-curl", required_argument, 0, "add a cron task invoking the specified url via CURL runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron_curl, NULL, UWSGI_OPT_MASTER},
{"curl-cron-legion", required_argument, 0, "add a cron task invoking the specified url via CURL runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron_curl, NULL, UWSGI_OPT_MASTER},
{"cron-curl-legion", required_argument, 0, "add a cron task invoking the specified url via CURL runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron_curl, NULL, UWSGI_OPT_MASTER},
#endif
{ 0, 0, 0, 0, 0, 0, 0},
};
struct uwsgi_plugin curl_cron_plugin = {
.name = "curl_cron",
.options = curl_cron_options,
};
+6
View File
@@ -0,0 +1,6 @@
NAME='curl_cron'
CFLAGS = []
LDFLAGS = []
LIBS = ['-lcurl']
GCC_LIST = ['curl_cron']
+2 -2
View File
@@ -49,7 +49,7 @@ void uwsgi_imperial_monitor_amqp_event(struct uwsgi_emperor_scanner *ues) {
}
if (msgsize > 0) {
emperor_add(ues, amqp_routing_key, uwsgi_now(), config, msgsize, 0, 0);
emperor_add(ues, amqp_routing_key, uwsgi_now(), config, msgsize, 0, 0, NULL);
}
end0:
@@ -88,7 +88,7 @@ end0:
emperor_respawn(ui_current, uwsgi_now());
}
else {
emperor_add(ues, config_file, uwsgi_now(), NULL, 0, 0, 0);
emperor_add(ues, config_file, uwsgi_now(), NULL, 0, 0, 0, NULL);
}
free(config_file);
+4 -2
View File
@@ -1,4 +1,4 @@
#include "../../uwsgi.h"
#include <uwsgi.h>
#include "client/dbclient.h"
@@ -60,7 +60,9 @@ extern "C" void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *ues
vassal_gid = tmp_gid;
}
uwsgi_emperor_simple_do(ues, (char *) name, (char *) config, vassal_ts/1000, vassal_uid, vassal_gid);
const char *socket_name = p.getStringField("socket");
uwsgi_emperor_simple_do(ues, (char *) name, (char *) config, vassal_ts/1000, vassal_uid, vassal_gid, (char *) socket_name);
}
+1 -1
View File
@@ -1,4 +1,4 @@
#include "../../uwsgi.h"
#include <uwsgi.h>
void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *);
void uwsgi_imperial_monitor_mongodb_init(struct uwsgi_emperor_scanner *);
+8 -1
View File
@@ -1,7 +1,14 @@
import os
NAME='emperor_mongodb'
CFLAGS = ['-I/usr/include/mongo','-I/usr/local/include/mongo']
LDFLAGS = []
LIBS = ['-lmongoclient', '-lboost_thread','-lboost_filesystem']
LIBS = []
if not 'UWSGI_MONGODB_NOLIB' in os.environ:
LIBS.append('-lmongoclient')
LIBS.append('-lboost_thread')
LIBS.append('-lboost_filesystem')
GCC_LIST = ['plugin', 'emperor_mongodb.cc']
+5 -1
View File
@@ -68,7 +68,11 @@ void uwsgi_imperial_monitor_pg(struct uwsgi_emperor_scanner *ues) {
vassal_uid = uwsgi_str_num(q_uid, strlen(q_uid));
vassal_gid = uwsgi_str_num(q_gid, strlen(q_gid));
}
uwsgi_emperor_simple_do(ues, name, config, uwsgi_str_num(ts, len), vassal_uid, vassal_gid);
char *socket_name = NULL;
if (PQnfields(res) > 5) {
socket_name = PQgetvalue(res, i, 5);
}
uwsgi_emperor_simple_do(ues, name, config, uwsgi_str_num(ts, len), vassal_uid, vassal_gid, socket_name);
}
}
+23 -4
View File
@@ -64,15 +64,16 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
int64_t more = 0;
size_t more_size = sizeof(more);
int i;
zmq_msg_t msg[5];
zmq_msg_t msg[6];
zmq_msg_init(&msg[0]);
zmq_msg_init(&msg[1]);
zmq_msg_init(&msg[2]);
zmq_msg_init(&msg[3]);
zmq_msg_init(&msg[4]);
zmq_msg_init(&msg[5]);
for(i=0;i<5;i++) {
for(i=0;i<6;i++) {
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0)
zmq_recvmsg(ues->data, &msg[i], ZMQ_DONTWAIT);
#else
@@ -105,6 +106,11 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
char *ez_gid = NULL;
size_t ez_gid_len = 0;
char *ez_socket_name = NULL;
size_t ez_socket_name_len = 0;
char *socket_name = NULL;
// config
if (i > 1) {
ez_config = zmq_msg_data(&msg[2]);
@@ -123,6 +129,12 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
ez_gid_len = zmq_msg_size(&msg[4]);
}
// gid
if (i > 4) {
ez_socket_name = zmq_msg_data(&msg[5]);
ez_socket_name_len = zmq_msg_size(&msg[5]);
}
char *name = uwsgi_concat2n(ez_name, ez_name_len, "", 0);
// ok let's start checking commands
@@ -142,10 +154,16 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
vassal_gid = uwsgi_str_num(ez_gid, ez_gid_len);
}
uwsgi_emperor_simple_do(ues, name, config, uwsgi_now(), vassal_uid, vassal_gid);
if (ez_socket_name) {
socket_name = uwsgi_concat2n(ez_socket_name, ez_socket_name_len, "", 0);
}
uwsgi_emperor_simple_do(ues, name, config, uwsgi_now(), vassal_uid, vassal_gid, socket_name);
if (config) {
free(config);
}
if (socket_name) {
free(socket_name);
}
}
// destroy an instance
else if (!uwsgi_strncmp(ez_cmd, ez_cmd_len, "destroy", 6)) {
@@ -158,7 +176,7 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
}
}
else {
uwsgi_log("[emperor-zeromq] unkonwn command \"%.*s\"\n", (int)ez_cmd_len, ez_cmd);
uwsgi_log("[emperor-zeromq] unknown command \"%.*s\"\n", (int)ez_cmd_len, ez_cmd);
}
free(name);
@@ -168,6 +186,7 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
zmq_msg_close(&msg[2]);
zmq_msg_close(&msg[3]);
zmq_msg_close(&msg[4]);
zmq_msg_close(&msg[5]);
}
// this is the event manager
+2 -1
View File
@@ -2,6 +2,7 @@
extern struct uwsgi_server uwsgi;
extern struct uwsgi_rack ur;
extern struct uwsgi_plugin rack_plugin;
struct ufib {
int enabled;
@@ -45,7 +46,7 @@ static void fiber_schedule_to_req() {
int error = 0;
rb_protect(rb_fiber_schedule_to_req, 0, &error);
if (error) {
uwsgi_ruby_exception();
rack_plugin.exception_log(NULL);
rb_gc_unregister_address(&ufiber.fib[id]);
uwsgi.wsgi_req->async_status = UWSGI_OK;
}
+141
View File
@@ -0,0 +1,141 @@
#include <uwsgi.h>
#include <GeoIP.h>
#include <GeoIPCity.h>
struct uwsgi_geoip {
char *country_db;
char *city_db;
GeoIP *country;
GeoIP *city;
} ugeoip;
struct uwsgi_option uwsgi_geoip_options[] = {
{"geoip-country", required_argument, 0, "load the specified geoip country database", uwsgi_opt_set_str, &ugeoip.country_db, 0},
{"geoip-city", required_argument, 0, "load the specified geoip city database", uwsgi_opt_set_str, &ugeoip.city_db, 0},
{ 0, 0, 0, 0, 0, 0, 0 }
};
static int uwsgi_geoip_init() {
if (ugeoip.country_db) {
ugeoip.country = GeoIP_open(ugeoip.country_db, GEOIP_MEMORY_CACHE);
if (!ugeoip.country) {
uwsgi_log("unable to open GeoIP country database: %s\n", ugeoip.country_db);
exit(1);
}
}
if (ugeoip.city_db) {
ugeoip.city = GeoIP_open(ugeoip.city_db, GEOIP_MEMORY_CACHE);
if (!ugeoip.city) {
uwsgi_log("unable to open GeoIP city database: %s\n", ugeoip.city_db);
exit(1);
}
}
return 0;
}
static char *uwsgi_route_var_geoip(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
uint32_t ip;
char ip_str[16];
// should be enough for geo coords
char lonlat[64];
memset(ip_str, 0, 16);
memcpy(ip_str, wsgi_req->remote_addr, wsgi_req->remote_addr_len);
if (inet_pton(AF_INET, ip_str, &ip) <= 0) {
return NULL;
}
ip = htonl(ip);
char *value = NULL;
// always prefer the city database;
GeoIP *g = ugeoip.city;
if (!g) {
g = ugeoip.country;
if (g) {
if (!uwsgi_strncmp(key, keylen, "country_code", 12)) {
value = (char *) GeoIP_country_code_by_ipnum(g, ip);
}
else if (!uwsgi_strncmp(key, keylen, "country_code3", 13)) {
value = (char *) GeoIP_country_code3_by_ipnum(g, ip);
}
else if (!uwsgi_strncmp(key, keylen, "country_name", 12)) {
value = (char *) GeoIP_country_name_by_ipnum(g, ip);
}
if (value) {
*vallen = strlen(value);
return uwsgi_str(value);
}
}
return NULL;
}
GeoIPRecord *gr = GeoIP_record_by_ipnum(g, ip);
if (!gr) return NULL;
// ok let's generate the output
if (!uwsgi_strncmp(key, keylen, "continent", 9)) {
value = gr->continent_code;
}
else if (!uwsgi_strncmp(key, keylen, "country_code", 12)) {
value = gr->country_code;
}
else if (!uwsgi_strncmp(key, keylen, "country_code3", 13)) {
value = gr->country_code3;
}
else if (!uwsgi_strncmp(key, keylen, "country_name", 12)) {
value = gr->country_name;
}
else if (!uwsgi_strncmp(key, keylen, "region", 6)) {
value = gr->region;
}
else if (!uwsgi_strncmp(key, keylen, "region_name", 11)) {
value = (char *) GeoIP_region_name_by_code(gr->country_code, gr->region);
}
else if (!uwsgi_strncmp(key, keylen, "city", 4)) {
value = gr->city;
}
else if (!uwsgi_strncmp(key, keylen, "postal_code", 11)) {
value = gr->postal_code;
}
else if (!uwsgi_strncmp(key, keylen, "latitude", 8) || !uwsgi_strncmp(key, keylen, "lat", 3)) {
snprintf(lonlat, 64, "%f", gr->latitude);
value = lonlat;
}
else if (!uwsgi_strncmp(key, keylen, "longitude", 9) || !uwsgi_strncmp(key, keylen, "lon", 3)) {
snprintf(lonlat, 64, "%f", gr->longitude);
value = lonlat;
}
else if (!uwsgi_strncmp(key, keylen, "dma", 3)) {
snprintf(lonlat, 64, "%d", gr->dma_code);
value = lonlat;
}
else if (!uwsgi_strncmp(key, keylen, "area", 4)) {
snprintf(lonlat, 64, "%d", gr->area_code);
value = lonlat;
}
if (value) {
*vallen = strlen(value);
char *ret = uwsgi_str(value);
GeoIPRecord_delete(gr);
return ret;
}
GeoIPRecord_delete(gr);
return NULL;
}
static void register_route_vars_geoip() {
struct uwsgi_route_var *urv = uwsgi_register_route_var("geoip", uwsgi_route_var_geoip);
urv->need_free = 1;
}
struct uwsgi_plugin geoip_plugin = {
.name = "geoip",
.options = uwsgi_geoip_options,
.init = uwsgi_geoip_init,
.on_load = register_route_vars_geoip,
};
+8
View File
@@ -0,0 +1,8 @@
NAME='geoip'
CFLAGS = []
LDFLAGS = []
LIBS = ['-lGeoIP']
GCC_LIST = ['geoip']
+11 -1
View File
@@ -18,6 +18,7 @@ static void uwsgi_opt_setup_gevent(char *opt, char *value, void *null) {
static struct uwsgi_option gevent_options[] = {
{"gevent", required_argument, 0, "a shortcut enabling gevent loop engine with the specified number of async cores and optimal parameters", uwsgi_opt_setup_gevent, NULL, UWSGI_OPT_THREADS},
{"gevent-monkey-patch", no_argument, 0, "call gevent.monkey.patch_all() automatically on startup", uwsgi_opt_true, &ugevent.monkey, 0},
{0, 0, 0, 0, 0, 0, 0},
};
@@ -317,6 +318,16 @@ static void gevent_loop() {
exit(1);
}
// call gevent.monkey.patch_all() if requested
if (ugevent.monkey) {
PyObject *gevent_monkey_dict = get_uwsgi_pydict("gevent.monkey");
if (!gevent_monkey_dict) uwsgi_pyexit;
PyObject *gevent_monkey_patch_all = PyDict_GetItemString(gevent_monkey_dict, "patch_all");
if (!gevent_monkey_patch_all) uwsgi_pyexit;
PyObject *ret = python_call(gevent_monkey_patch_all, PyTuple_New(0), 0, NULL);
if (!ret) uwsgi_pyexit;
}
ugevent.spawn = PyDict_GetItemString(gevent_dict, "spawn");
if (!ugevent.spawn) uwsgi_pyexit;
@@ -329,7 +340,6 @@ static void gevent_loop() {
ugevent.greenlet_switch_args = PyTuple_New(0);
Py_INCREF(ugevent.greenlet_switch_args);
PyObject *gevent_get_hub = PyDict_GetItemString(gevent_dict, "get_hub");
ugevent.hub = python_call(gevent_get_hub, PyTuple_New(0), 0, NULL);
+1
View File
@@ -52,5 +52,6 @@ struct uwsgi_gevent {
PyObject *signal_watcher;
PyObject **watchers;
int destroy;
int monkey;
};
+1 -1
View File
@@ -150,7 +150,7 @@ func CacheGet(key string, cache string) []byte {
var p []byte
c_value := C.uwsgi_cache_magic_get(k, C.uint16_t(kl), &vl, c)
c_value := C.uwsgi_cache_magic_get(k, C.uint16_t(kl), &vl, (*C.uint64_t)(nil), c)
if c_value != nil {
p = C.GoBytes((unsafe.Pointer)(c_value), C.int(vl))
+281
View File
@@ -0,0 +1,281 @@
#include <uwsgi.h>
#include <client/dbclient.h>
#include <client/gridfs.h>
struct uwsgi_gridfs_mountpoint {
char *mountpoint;
uint16_t mountpoint_len;
char *server;
char *db;
char *timeout_str;
int timeout;
char *no_mime;
char *orig_filename;
char *md5;
char *etag;
char *prefix;
char *itemname;
uint16_t itemname_len;
char *skip_slash;
uint16_t prefix_len;
char *username;
char *password;
};
struct uwsgi_gridfs {
int debug;
struct uwsgi_string_list *mountpoints;
} ugridfs;
struct uwsgi_option uwsgi_gridfs_options[] = {
{(char *)"gridfs-mount", required_argument, 0, (char *)"mount a gridfs db on the specified mountpoint", uwsgi_opt_add_string_list, &ugridfs.mountpoints, UWSGI_OPT_MIME},
{(char *)"gridfs-debug", no_argument, 0, (char *)"report gridfs mountpoint and itemname for each request (debug)", uwsgi_opt_true, &ugridfs.debug, UWSGI_OPT_MIME},
{0, 0, 0, 0, 0, 0, 0},
};
extern struct uwsgi_server uwsgi;
extern struct uwsgi_plugin gridfs_plugin;
static void uwsgi_gridfs_do(struct wsgi_request *wsgi_req, struct uwsgi_gridfs_mountpoint *ugm, char *itemname, int need_free) {
try {
mongo::scoped_ptr<mongo::ScopedDbConnection> conn( mongo::ScopedDbConnection::getScopedDbConnection(ugm->server, ugm->timeout) );
try {
if (ugm->username && ugm->password) {
std::string errmsg;
if ((*conn).conn().auth(ugm->db, ugm->username, ugm->password, errmsg)) {
uwsgi_log("[uwsgi-gridfs]: %s\n", errmsg.c_str());
(*conn).done();
uwsgi_403(wsgi_req);
return;
}
}
mongo::GridFS gridfs((*conn).conn(), ugm->db);
mongo::GridFile gfile = gridfs.findFile(itemname);
if (need_free) {
free(itemname);
itemname = NULL;
}
if (!gfile.exists()) {
(*conn).done();
uwsgi_404(wsgi_req);
return;
}
uwsgi_response_prepare_headers(wsgi_req, (char *)"200 OK", 6);
// first get the content_type (if possibile)
std::string filename = gfile.getFilename();
if (!ugm->no_mime) {
size_t mime_type_len = 0;
char *mime_type = uwsgi_get_mime_type((char *)filename.c_str(), filename.length(), &mime_type_len);
if (mime_type) {
uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_len);
}
}
if (ugm->orig_filename) {
char *filename_header = uwsgi_concat3((char *)"inline; filename=\"", (char *)filename.c_str(), (char *)"\"");
uwsgi_response_add_header(wsgi_req, (char *)"Content-Disposition", 19, filename_header, 19 + filename.length());
free(filename_header);
}
uwsgi_response_add_content_length(wsgi_req, gfile.getContentLength());
if (ugm->etag) {
std::string g_md5 = gfile.getMD5();
if (!g_md5.empty()) {
char *etag = uwsgi_concat3((char *)"\"", (char *)g_md5.c_str(), (char *)"\"");
uwsgi_response_add_header(wsgi_req, (char *)"ETag", 4, etag, 2+g_md5.length());
free(etag);
}
}
if (ugm->md5) {
std::string g_md5 = gfile.getMD5();
size_t base64_len = 0;
char *base64 = uwsgi_base64_encode((char *)g_md5.c_str(), g_md5.length(), &base64_len);
uwsgi_response_add_header(wsgi_req, (char *) "Content-MD5", 11, base64, base64_len);
free(base64);
}
if (uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, (char *)"HEAD", 4)) {
int nc = gfile.getNumChunks();
int i;
for(i=0;i<nc;i++) {
mongo::GridFSChunk gchunk = gfile.getChunk(i);
int chunk_len = 0;
const char *chunk = gchunk.data(chunk_len);
uwsgi_response_write_body_do(wsgi_req, (char *) chunk, chunk_len);
}
}
(*conn).done();
}
catch ( mongo::DBException &e ) {
uwsgi_log("[uwsgi-gridfs]: %s\n", e.what());
(*conn).done();
if (need_free && itemname) {
free(itemname);
itemname = NULL;
}
}
}
catch ( mongo::DBException &e ) {
uwsgi_log("[uwsgi-gridfs]: %s\n", e.what());
if (need_free && itemname) {
free(itemname);
itemname = NULL;
}
}
}
static struct uwsgi_gridfs_mountpoint *uwsgi_gridfs_add_mountpoint(char *arg, size_t arg_len) {
struct uwsgi_gridfs_mountpoint *ugm = (struct uwsgi_gridfs_mountpoint *) uwsgi_calloc(sizeof(struct uwsgi_gridfs_mountpoint));
if (uwsgi_kvlist_parse(arg, arg_len, ',', '=',
"mountpoint", &ugm->mountpoint,
"server", &ugm->server,
"db", &ugm->db,
"prefix", &ugm->prefix,
"no_mime", &ugm->no_mime,
"timeout", &ugm->timeout_str,
"orig_filename", &ugm->orig_filename,
"skip_slash", &ugm->skip_slash,
"md5", &ugm->md5,
"etag", &ugm->etag,
"itemname", &ugm->itemname,
"item", &ugm->itemname,
"username", &ugm->username,
"password", &ugm->password,
NULL)) {
uwsgi_log("invalid gridfs mountpoint syntax\n");
free(ugm);
return NULL;
}
if (!ugm->db) {
uwsgi_log("you need to specify a \"db\" name for gridfs\n");
free(ugm);
return NULL;
}
if (!ugm->mountpoint) {
ugm->mountpoint = (char *)"";
}
ugm->mountpoint_len = strlen(ugm->mountpoint);
if (!ugm->server) {
ugm->server = (char *)"127.0.0.1:27017";
}
if (ugm->timeout_str) {
ugm->timeout = atoi(ugm->timeout_str);
}
else {
ugm->timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
}
if (ugm->prefix) {
ugm->prefix_len = strlen(ugm->prefix);
}
if (ugm->itemname) {
ugm->itemname_len = strlen(ugm->itemname);
}
return ugm;
}
extern "C" int uwsgi_gridfs_request(struct wsgi_request *wsgi_req) {
// this is the gridfs file
char *itemname = NULL;
/* Standard GridFS request */
if (!wsgi_req->uh->pktsize) {
uwsgi_log( "Empty GridFS request. skip.\n");
return -1;
}
if (uwsgi_parse_vars(wsgi_req)) {
return -1;
}
wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, gridfs_plugin.modifier1);
if (ugridfs.debug) {
uwsgi_log("[uwsgi-gridfs-debug] app_id = %d\n", wsgi_req->app_id);
}
if (wsgi_req->app_id == -1) {
uwsgi_404(wsgi_req);
return UWSGI_OK;
}
struct uwsgi_app *ua = &uwsgi_apps[wsgi_req->app_id];
struct uwsgi_gridfs_mountpoint *ugm = (struct uwsgi_gridfs_mountpoint *) ua->interpreter;
if (ugm->skip_slash && (wsgi_req->path_info_len > 0 && wsgi_req->path_info[0] == '/')) {
itemname = uwsgi_concat2n(ugm->prefix, ugm->prefix_len, wsgi_req->path_info+1, wsgi_req->path_info_len-1);
}
else {
itemname = uwsgi_concat2n(ugm->prefix, ugm->prefix_len, wsgi_req->path_info, wsgi_req->path_info_len);
}
if (ugridfs.debug) {
uwsgi_log("[uwsgi-gridfs-debug] itemname = %s\n", itemname);
}
// itemname will be freed here
uwsgi_gridfs_do(wsgi_req, ugm, itemname, 1);
return UWSGI_OK;
}
extern "C" void uwsgi_gridfs_mount() {
if (!uwsgi.skip_atexit) {
uwsgi_log("*** WARNING libmongoclient could have a bug with atexit() hooks, if you get segfault on end/reload, add --skip-atexit ***\n");
}
struct uwsgi_string_list *usl = ugridfs.mountpoints;
while(usl) {
if (uwsgi_apps_cnt >= uwsgi.max_apps) {
uwsgi_log("ERROR: you cannot load more than %d apps in a worker\n", uwsgi.max_apps);
exit(1);
}
int id = uwsgi_apps_cnt;
struct uwsgi_gridfs_mountpoint *ugm = uwsgi_gridfs_add_mountpoint(uwsgi_str(usl->value), usl->len);
if (!ugm) exit(1);
uwsgi_add_app(id, gridfs_plugin.modifier1, ugm->mountpoint, ugm->mountpoint_len, ugm, ugm);
uwsgi_emulate_cow_for_apps(id);
uwsgi_log("GridFS mountpoint \"%.*s\" (%d) added: server=%s db=%s\n", ugm->mountpoint_len, ugm->mountpoint, id, ugm->server, ugm->db);
usl = usl->next;
}
}
#ifdef UWSGI_ROUTING
static int uwsgi_routing_func_gridfs(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
struct uwsgi_gridfs_mountpoint *ugm = (struct uwsgi_gridfs_mountpoint *) ur->data2;
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub_itemname = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ugm->itemname, ugm->itemname_len);
if (!ub_itemname) return UWSGI_ROUTE_BREAK;
if (ugridfs.debug) {
uwsgi_log("[uwsgi-gridfs-debug] itemname = %s\n", ub_itemname->buf);
}
uwsgi_gridfs_do(wsgi_req, ugm, ub_itemname->buf, 0);
uwsgi_buffer_destroy(ub_itemname);
return UWSGI_ROUTE_BREAK;
}
extern "C" int uwsgi_router_gridfs(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_gridfs;
ur->data = args;
ur->data_len = strlen(args);
ur->data2 = uwsgi_gridfs_add_mountpoint((char *)ur->data, ur->data_len);
if (!ur->data2) {
exit(1);
}
return 0;
}
#endif
+31
View File
@@ -0,0 +1,31 @@
#include <uwsgi.h>
int uwsgi_gridfs_request(struct wsgi_request *);
void uwsgi_gridfs_mount();
extern struct uwsgi_option uwsgi_gridfs_options[];
static void uwsgi_gridfs_log(struct wsgi_request *wsgi_req) {
log_request(wsgi_req);
}
#ifdef UWSGI_ROUTING
int uwsgi_router_gridfs(struct uwsgi_route *, char *);
static void uwsgi_gridfs_register_router() {
uwsgi_register_router("gridfs", uwsgi_router_gridfs);
}
#endif
struct uwsgi_plugin gridfs_plugin = {
.name = "gridfs",
.modifier1 = 25,
.init_apps = uwsgi_gridfs_mount,
.options = uwsgi_gridfs_options,
.request = uwsgi_gridfs_request,
.after_request = uwsgi_gridfs_log,
#ifdef UWSGI_ROUTING
.on_load = uwsgi_gridfs_register_router,
#endif
};
+16
View File
@@ -0,0 +1,16 @@
import os
NAME='gridfs'
CFLAGS = ['-I/usr/include/mongo','-I/usr/local/include/mongo']
LDFLAGS = []
LIBS = []
if not 'UWSGI_MONGODB_NOLIB' in os.environ:
LIBS.append('-lmongoclient')
LIBS.append('-lstdc++')
LIBS.append('-lboost_thread')
LIBS.append('-lboost_system')
LIBS.append('-lboost_filesystem')
GCC_LIST = ['plugin', 'gridfs.cc']
+15 -10
View File
@@ -90,31 +90,35 @@ int http_add_uwsgi_header(struct corerouter_peer *peer, char *hh, uint16_t hhlen
if (!keylen)
return -1;
if (!uwsgi_strncmp("HOST", 4, hh, keylen)) {
peer->key = val;
peer->key_len = vallen;
}
else if (hr->websockets) {
if (hr->websockets) {
if (!uwsgi_strncmp("UPGRADE", 7, hh, keylen)) {
if (!uwsgi_strnicmp(val, vallen, "websocket", 9)) {
hr->websockets++;
}
goto done;
}
else if (!uwsgi_strncmp("CONNECTION", 10, hh, keylen)) {
if (!uwsgi_strnicmp(val, vallen, "Upgrade", 7)) {
hr->websockets++;
}
goto done;
}
else if (!uwsgi_strncmp("SEC_WEBSOCKET_VERSION", 21, hh, keylen)) {
hr->websockets++;
hr->websockets++;
goto done;
}
else if (!uwsgi_strncmp("SEC_WEBSOCKET_KEY", 17, hh, keylen)) {
hr->websocket_key = val;
hr->websocket_key_len = vallen;
goto done;
}
}
if (!uwsgi_strncmp("HOST", 4, hh, keylen)) {
peer->key = val;
peer->key_len = vallen;
}
else if (!uwsgi_strncmp("CONTENT_LENGTH", 14, hh, keylen)) {
hr->content_length = uwsgi_str_num(val, vallen);
hr->session.can_keepalive = 0;
@@ -139,12 +143,13 @@ int http_add_uwsgi_header(struct corerouter_peer *peer, char *hh, uint16_t hhlen
}
#endif
done:
if (uwsgi_strncmp("CONTENT_TYPE", 12, hh, keylen) && uwsgi_strncmp("CONTENT_LENGTH", 14, hh, keylen)) {
keylen += 5;
prefix = 1;
}
if (uwsgi_buffer_u16le(out, keylen)) return -1;
if (prefix) {
@@ -587,6 +592,8 @@ ssize_t http_parse(struct corerouter_peer *main_peer) {
size_t len = main_peer->in->pos;
char *ptr = main_peer->in->buf;
hr->rnrn = 0;
for (j = 0; j < len; j++) {
if (*ptr == '\r' && (hr->rnrn == 0 || hr->rnrn == 2)) {
hr->rnrn++;
@@ -770,8 +777,6 @@ int http_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_gateway_socket
}
hr->rnrn = 0;
hr->port = ugs->port;
hr->port_len = ugs->port_len;
switch(ugs->mode) {
+2
View File
@@ -108,3 +108,5 @@ int uwsgi_jvm_object_to_response_body(struct wsgi_request *, jobject);
jobject uwsgi_jvm_bytearray(char *, size_t);
char *uwsgi_jvm_bytearray2c(jobject);
void uwsgi_jvm_release_bytearray(jobject, char *);
jobject uwsgi_jvm_to_string(jobject);
+34 -11
View File
@@ -41,7 +41,7 @@ JNIEXPORT void JNICALL uwsgi_jvm_api_register_signal(JNIEnv *env, jclass c, jint
JNIEXPORT void JNICALL uwsgi_jvm_api_register_rpc(JNIEnv *env, jclass c, jstring name, jobject func) {
// no need to release it
char *n = uwsgi_jvm_str2c(name);
if (uwsgi_register_rpc(n, jvm_plugin.modifier1, 0, uwsgi_jvm_ref(func))) {
if (uwsgi_register_rpc(n, &jvm_plugin, 0, uwsgi_jvm_ref(func))) {
uwsgi_jvm_throw("unable to register rpc function");
}
}
@@ -79,7 +79,7 @@ JNIEXPORT jobject JNICALL uwsgi_jvm_api_cache_get(JNIEnv *env, jclass c, jstring
size_t keylen = uwsgi_jvm_strlen(jkey);
char *key = uwsgi_jvm_str2c(jkey);
uint64_t vallen = 0;
char *value = uwsgi_cache_magic_get(key, keylen, &vallen, NULL);
char *value = uwsgi_cache_magic_get(key, keylen, &vallen, NULL, NULL);
uwsgi_jvm_release_chars(jkey, key);
if (value) {
jobject o = uwsgi_jvm_bytearray(value, vallen);
@@ -99,7 +99,7 @@ JNIEXPORT jobject JNICALL uwsgi_jvm_api_cache_get_name(JNIEnv *env, jclass c, js
char *key = uwsgi_jvm_str2c(jkey);
char *cache = uwsgi_jvm_str2c(jcache);
uint64_t vallen = 0;
char *value = uwsgi_cache_magic_get(key, keylen, &vallen, cache);
char *value = uwsgi_cache_magic_get(key, keylen, &vallen, NULL, cache);
uwsgi_jvm_release_chars(jkey, key);
uwsgi_jvm_release_chars(jcache, cache);
if (value) {
@@ -243,6 +243,15 @@ jobject uwsgi_jvm_entryset(jobject o) {
return uwsgi_jvm_call_object(o, mid);
}
jobject uwsgi_jvm_to_string(jobject o) {
jclass c = uwsgi_jvm_class_from_object(o);
if (!c) return NULL;
jmethodID mid = uwsgi_jvm_get_method_id_quiet(c, "toString", "()Ljava/lang/String;");
uwsgi_jvm_local_unref(c);
if (!mid) return NULL;
return uwsgi_jvm_call_object(o, mid);
}
int uwsgi_jvm_object_to_response_body(struct wsgi_request *wsgi_req, jobject body) {
// check for string
@@ -297,20 +306,35 @@ int uwsgi_jvm_object_to_response_body(struct wsgi_request *wsgi_req, jobject bod
ret = uwsgi_response_write_body_do(wsgi_req, c_body, c_body_len);
uwsgi_jvm_release_chars(chunk, c_body);
uwsgi_jvm_local_unref(chunk);
if (ret) goto done;
continue;
}
else if (uwsgi_jvm_object_is_instance(chunk, ujvm.bytearray_class)) {
if (uwsgi_jvm_object_is_instance(chunk, ujvm.bytearray_class)) {
char *c_body = uwsgi_jvm_bytearray2c(chunk);
size_t c_body_len = uwsgi_jvm_array_len(chunk);
ret = uwsgi_response_write_body_do(wsgi_req, c_body, c_body_len);
uwsgi_jvm_release_bytearray(chunk, c_body);
uwsgi_jvm_local_unref(chunk);
if (ret) goto done;
continue;
}
else {
uwsgi_log("body iterable item must be java/lang/String or array of bytes!!!\n");
uwsgi_jvm_local_unref(chunk);
goto done;
jobject str_o = uwsgi_jvm_to_string(chunk);
if (str_o) {
char *c_body = uwsgi_jvm_str2c(str_o);
size_t c_body_len = uwsgi_jvm_strlen(str_o);
ret = uwsgi_response_write_body_do(wsgi_req, c_body, c_body_len);
uwsgi_jvm_release_chars(str_o, c_body);
uwsgi_jvm_local_unref(str_o);
uwsgi_jvm_local_unref(chunk);
if (ret) goto done;
continue;
}
if (ret) goto done;
uwsgi_log("body iterable item must be java/lang/String or array of bytes!!!\n");
uwsgi_jvm_local_unref(chunk);
goto done;
}
done:
uwsgi_jvm_local_unref(chunks);
@@ -592,11 +616,10 @@ int uwsgi_jvm_consume_input_stream(struct wsgi_request *wsgi_req, size_t chunk,
break;
}
// get the body of the array
size_t buf_len = uwsgi_jvm_array_len(byte_buffer);
char *buf = (char *) (*ujvm_env)->GetByteArrayElements(ujvm_env, byte_buffer, JNI_FALSE);
if (!buf) { ret = -1; break; }
//send
if (uwsgi_response_write_body_do(wsgi_req, buf, buf_len)) {
if (uwsgi_response_write_body_do(wsgi_req, buf, len)) {
(*ujvm_env)->ReleaseByteArrayElements(ujvm_env, byte_buffer, (jbyte *) buf, 0);
ret = -1; break;
}
+27 -9
View File
@@ -1,4 +1,5 @@
import os,sys
import os
import shutil
NAME='jvm'
@@ -20,6 +21,9 @@ if operating_system == 'darwin':
if os.path.exists(jvm):
JVM_INCPATH = ["-Wno-deprecated-declarations", "-I%s" % jvm]
JVM_LIBPATH = ["-framework JavaVM"]
elif operating_system.startswith('cygwin'):
JVM_INCPATH = ['-I"/cygdrive/c/Program Files/Java/jdk1.7.0_17/include"', '-I"/cygdrive/c/Program Files/Java/jdk1.7.0_17/include/win32"']
JVM_LIBPATH = ['-L"/cygdrive/c/Program Files/Java/jdk1.7.0_17/jre/bin/server"']
else:
known_jvms = ('/usr/lib/jvm/java-7-openjdk', '/usr/local/openjdk7', '/usr/lib/jvm/java-6-openjdk', '/usr/local/openjdk', '/usr/java', '/usr/lib/jvm/java/')
for jvm in known_jvms:
@@ -33,15 +37,15 @@ else:
JVM_LIBPATH = ["-L%s/jre/lib/%s/server" % (jvm, arch)]
break
try:
JVM_INCPATH = os.environ['UWSGICONFIG_JVM_INCPATH']
except:
pass
try:
JVM_INCPATH = ['-I"' + os.environ['UWSGICONFIG_JVM_INCPATH'] + '"']
except:
pass
try:
JVM_LIBPATH = os.environ['UWSGICONFIG_JVM_LIBPATH']
except:
pass
try:
JVM_LIBPATH = ['-L"' + os.environ['UWSGICONFIG_JVM_LIBPATH'] + '"']
except:
pass
if not JVM_INCPATH or not JVM_LIBPATH:
print("unable to autodetect the JVM path, please specify UWSGICONFIG_JVM_INCPATH and UWSGICONFIG_JVM_LIBPATH environment vars")
@@ -66,3 +70,17 @@ def post_build(config):
if os.system("cd %s/plugins/jvm ; jar cvf uwsgi.jar *.class" % os.getcwd()) != 0:
os._exit(1)
print("*** uwsgi.jar available in %s/plugins/jvm/uwsgi.jar ***" % os.getcwd())
env = os.environ.get('VIRTUAL_ENV')
if env:
src = "%s/plugins/jvm/uwsgi.jar" % os.getcwd()
tgt = "%s/lib/uwsgi.jar" % env
shutil.copyfile(src, tgt)
print("*** uwsgi.jar had been copied to %s" % tgt)
plugin = "%s/jvm_plugin.so" % os.getcwd()
if os.path.exists(plugin):
tgt = "%s/bin/jvm_plugin.so" % env
shutil.copyfile(plugin, tgt)
print("*** jvm_plugin.so had been copied to %s" % tgt)
+29 -27
View File
@@ -1,6 +1,4 @@
#ifdef UWSGI_LDAP
#include "uwsgi.h"
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
@@ -14,7 +12,22 @@ extern struct uwsgi_server uwsgi;
#define ldap_unbind_ext_s ldap_unbind_ext
#endif
void ldap2uwsgi(char *ldapname, char *uwsginame) {
static void uwsgi_opt_ldap_dump(char *, char *, void *);
static void uwsgi_opt_ldap_dump_ldif(char *, char *, void *);
static void uwsgi_ldap_config(char *);
static void uwsgi_opt_load_ldap(char *opt, char *url, void *none) {
uwsgi_ldap_config(url);
}
static struct uwsgi_option uwsgi_ldap_options[] = {
{"ldap", required_argument, 0, "load configuration from ldap server", uwsgi_opt_load_ldap, NULL, UWSGI_OPT_IMMEDIATE},
{"ldap-schema", no_argument, 0, "dump uWSGI ldap schema", uwsgi_opt_ldap_dump, NULL, UWSGI_OPT_IMMEDIATE},
{"ldap-schema-ldif", no_argument, 0, "dump uWSGI ldap schema in ldif format", uwsgi_opt_ldap_dump_ldif, NULL, UWSGI_OPT_IMMEDIATE},
{0, 0, 0, 0, 0, 0, 0},
};
static void ldap2uwsgi(char *ldapname, char *uwsginame) {
char *ptr = uwsginame;
int i;
@@ -32,7 +45,7 @@ void ldap2uwsgi(char *ldapname, char *uwsginame) {
*ptr++ = 0;
}
int calc_ldap_name(char *name) {
static int calc_ldap_name(char *name) {
int i;
int counter = 0;
@@ -52,7 +65,7 @@ struct uwsgi_ldap_entry {
};
void uwsgi_name_to_ldap(char *src, char *dst) {
static void uwsgi_name_to_ldap(char *src, char *dst) {
int i;
char *ptr = dst;
@@ -77,22 +90,7 @@ void uwsgi_name_to_ldap(char *src, char *dst) {
}
struct uwsgi_ldap_entry *get_ldap_by_num(struct uwsgi_ldap_entry *root, int num, int count) {
int i;
struct uwsgi_ldap_entry *ule;
for (i = 0; i < count; i++) {
ule = &root[i];
if (ule->num == num) {
return ule;
}
}
return NULL;
}
struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *name, int count) {
static struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *name, int count) {
int i;
struct uwsgi_ldap_entry *ule;
@@ -106,7 +104,7 @@ struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *
return NULL;
}
struct uwsgi_ldap_entry *get_ldap_names(int *count) {
static struct uwsgi_ldap_entry *get_ldap_names(int *count) {
struct uwsgi_option *op = uwsgi.options;
struct uwsgi_ldap_entry *ule, *entry;
@@ -139,7 +137,7 @@ next:
return ule;
}
void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
static void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
int i;
int items;
@@ -192,7 +190,7 @@ void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
exit(0);
}
void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
static void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
int i;
int items;
@@ -240,7 +238,7 @@ void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
exit(0);
}
void uwsgi_ldap_config(char *url) {
static void uwsgi_ldap_config(char *url) {
LDAP *ldp;
LDAPMessage *results, *entry;
@@ -367,4 +365,8 @@ void uwsgi_ldap_config(char *url) {
ldap_unbind_ext_s(ldp, NULL, NULL);
}
#endif
struct uwsgi_plugin ldap_plugin = {
.name = "ldap",
.options = uwsgi_ldap_options,
};
+7
View File
@@ -0,0 +1,7 @@
NAME='ldap'
CFLAGS = []
LDFLAGS = []
LIBS = ['-lldap']
GCC_LIST = ['ldap']
@@ -0,0 +1,71 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
static int legion_action_cache_fetch_from_legion(struct uwsgi_legion *ul, char *arg) {
uwsgi_log("[legion-cache-fetch] getting cache '%s' dump from legion '%s' nodes\n", arg, ul->legion);
struct uwsgi_cache *uc = uwsgi_cache_by_name(arg);
if (!uc) {
uwsgi_log("[legion-cache-fetch] cannot sync, cache '%s' not found\n", arg);
return 1;
}
struct uwsgi_string_list *dump_from_nodes = NULL;
uwsgi_rlock(ul->lock);
struct uwsgi_legion_node *legion_nodes = ul->nodes_head;
while (legion_nodes) {
char *dump_socket = NULL;
if (uwsgi_kvlist_parse(legion_nodes->scroll, legion_nodes->scroll_len, ',', '=',
"dump-socket", &dump_socket,
NULL)) {
uwsgi_log("[legion-cache-fetch] cannot sync from %.*s, cache socket address not found in legion scroll: %.*s\n",
legion_nodes->name_len, legion_nodes->name, legion_nodes->scroll_len, legion_nodes->scroll);
}
else {
if (dump_socket) {
uwsgi_string_new_list(&dump_from_nodes, dump_socket);
}
else {
uwsgi_log("[legion-cache-fetch] cannot sync from %.*s, cache socket address not found in legion scroll: %.*s\n",
legion_nodes->name_len, legion_nodes->name, legion_nodes->scroll_len, legion_nodes->scroll);
}
}
legion_nodes = legion_nodes->next;
}
// update uc->sync_nodes list
struct uwsgi_string_list *usl = uc->sync_nodes;
struct uwsgi_string_list *next;
while (usl) {
next = usl->next;
free(usl->value);
free(usl);
usl = next;
}
uwsgi_rwunlock(ul->lock);
uwsgi_rlock(uc->lock);
uc->sync_nodes = dump_from_nodes;
uwsgi_rwunlock(uc->lock);
// call sync
uwsgi_cache_sync_from_nodes(uc);
return 0;
}
static void legion_cache_register() {
uwsgi_legion_action_register("legion-cache-fetch", legion_action_cache_fetch_from_legion);
}
struct uwsgi_plugin legion_cache_fetch_plugin = {
.name = "legion_cache_fetch",
.on_load = legion_cache_register,
};
@@ -0,0 +1,8 @@
NAME = 'legion_cache_fetch'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['legion_cache_fetch']
+173
View File
@@ -0,0 +1,173 @@
#include <uwsgi.h>
/*
this is an UDP logger encrypting each packet with the choosen algo, key and iv.
It is useful in cloud services without persistent storage for which you want to send logs to an external system.
Syntax: --logger/--req-logger crypto:addr=<udp_address>,algo=<algorithm>,secret=<key>,iv=<iv>,prefix=<prefix>
example:
uwsgi --plugin logcrypto --logger crypto:addr=127.0.0.1:1717,algo=bf-cbc,secret=ciaociao -M -p 4 -s :3031
*/
extern struct uwsgi_server uwsgi;
struct uwsgi_crypto_logger_conf {
EVP_CIPHER_CTX *encrypt_ctx;
char *addr;
char *algo;
char *secret;
char *iv;
char *prefix;
size_t prefix_len;
};
static void uwsgi_crypto_logger_setup_encryption(struct uwsgi_crypto_logger_conf *uclc) {
if (!uwsgi.ssl_initialized) {
uwsgi_ssl_init();
}
uclc->encrypt_ctx = uwsgi_malloc(sizeof(EVP_CIPHER_CTX));
EVP_CIPHER_CTX_init(uclc->encrypt_ctx);
const EVP_CIPHER *cipher = EVP_get_cipherbyname(uclc->algo);
if (!cipher) {
uwsgi_log_safe("[uwsgi-logcrypto] unable to find algorithm/cipher\n");
exit(1);
}
int cipher_len = EVP_CIPHER_key_length(cipher);
size_t s_len = strlen(uclc->secret);
if ((unsigned int) cipher_len > s_len) {
char *secret_tmp = uwsgi_malloc(cipher_len);
memcpy(secret_tmp, uclc->secret, s_len);
memset(secret_tmp + s_len, 0, cipher_len - s_len);
uclc->secret = secret_tmp;
}
int iv_len = EVP_CIPHER_iv_length(cipher);
size_t s_iv_len = 0;
if (uclc->iv) {
s_iv_len = strlen(uclc->iv);
}
if ((unsigned int) iv_len > s_iv_len) {
char *secret_tmp = uwsgi_malloc(iv_len);
memcpy(secret_tmp, uclc->iv, s_iv_len);
memset(secret_tmp + s_iv_len, '0', iv_len - s_iv_len);
uclc->iv = secret_tmp;
}
if (EVP_EncryptInit_ex(uclc->encrypt_ctx, cipher, NULL, (const unsigned char *) uclc->secret, (const unsigned char *) uclc->iv) <= 0) {
uwsgi_error_safe("uwsgi_crypto_logger_setup_encryption()/EVP_EncryptInit_ex()");
exit(1);
}
}
static ssize_t uwsgi_crypto_logger(struct uwsgi_logger *ul, char *message, size_t len) {
struct uwsgi_crypto_logger_conf *uclc = (struct uwsgi_crypto_logger_conf *) ul->data;
if (!ul->configured) {
uclc = uwsgi_calloc(sizeof(struct uwsgi_crypto_logger_conf));
if (uwsgi_kvlist_parse(ul->arg, strlen(ul->arg), ',', '=',
"addr", &uclc->addr,
"algo", &uclc->algo,
"secret", &uclc->secret,
"iv", &uclc->iv,
"prefix", &uclc->prefix,
NULL)) {
uwsgi_log_safe("[uwsgi-logcrypto] unable to parse options\n");
exit(1);
}
if (!uclc->addr || !uclc->algo || !uclc->secret) {
uwsgi_log_safe("[uwsgi-logcrypto] you have to specify at least addr,algo and secret options\n");
exit(1);
}
if (uclc->prefix) {
uclc->prefix_len = strlen(uclc->prefix);
}
char *colon = strchr(uclc->addr, ':');
if (!colon) {
uwsgi_log_safe("[uwsgi-logcrypto] invalid UDP address\n");
exit(1);
}
ul->addr_len = socket_to_in_addr(uclc->addr, colon, 0, &ul->addr.sa_in);
ul->fd = socket(AF_INET, SOCK_DGRAM, 0);
if (ul->fd < 0) {
uwsgi_error_safe("uwsgi_crypto_logger()/socket()");
exit(1);
}
uwsgi_crypto_logger_setup_encryption(uclc);
ul->data = uclc;
ul->configured = 1;
}
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
if (uwsgi_buffer_num64(ub, uwsgi_micros())) goto error;
if (uwsgi_buffer_append(ub, " ", 1)) goto error;
if (uclc->prefix) {
if (uwsgi_buffer_append(ub, uclc->prefix, uclc->prefix_len)) goto error;
if (uwsgi_buffer_append(ub, " ", 1)) goto error;
}
if (uwsgi_buffer_append(ub, message, len)) goto error;
// let's encrypt the message
unsigned char *encrypted = uwsgi_malloc(ub->pos + EVP_MAX_BLOCK_LENGTH);
if (EVP_EncryptInit_ex(uclc->encrypt_ctx, NULL, NULL, NULL, NULL) <= 0) {
uwsgi_error_safe("[uwsgi-logcrypto] EVP_EncryptInit_ex()");
free(encrypted);
goto error;
}
int e_len = 0;
if (EVP_EncryptUpdate(uclc->encrypt_ctx, encrypted, &e_len, (unsigned char *) ub->buf, ub->pos) <= 0) {
uwsgi_error("[uwsgi-logcrypto] EVP_EncryptUpdate()");
free(encrypted);
goto error;
}
int tmplen = 0;
if (EVP_EncryptFinal_ex(uclc->encrypt_ctx, encrypted + e_len, &tmplen) <= 0) {
uwsgi_error("[uwsgi-logcrypto] EVP_EncryptFinal_ex()");
free(encrypted);
goto error;
}
uwsgi_buffer_destroy(ub);
ssize_t rlen = sendto(ul->fd, encrypted, e_len + tmplen, 0, (struct sockaddr *) &ul->addr.sa_in, ul->addr_len);
free(encrypted);
return rlen;
error:
uwsgi_buffer_destroy(ub);
return -1;
}
static void uwsgi_logcrypto_register() {
uwsgi_register_logger("crypto", uwsgi_crypto_logger);
}
struct uwsgi_plugin logcrypto_plugin = {
.name = "logcrypto",
.on_load = uwsgi_logcrypto_register,
};
+6
View File
@@ -0,0 +1,6 @@
NAME='logcrypto'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['logcrypto']
+169 -26
View File
@@ -1,4 +1,4 @@
#include "../../uwsgi.h"
#include <uwsgi.h>
#include <lua.h>
#include <lualib.h>
@@ -8,15 +8,33 @@ extern struct uwsgi_server uwsgi;
struct uwsgi_lua {
struct lua_State **L;
char *shell;
char *filename;
struct uwsgi_string_list *load;
} ulua;
struct uwsgi_plugin lua_plugin;
#define lca(L, n) ulua_check_args(L, __FUNCTION__, n)
static void uwsgi_opt_luashell(char *opt, char *value, void *foobar) {
uwsgi.honour_stdin = 1;
if (value) {
ulua.shell = value;
}
else {
ulua.shell = "";
}
}
static struct uwsgi_option uwsgi_lua_options[] = {
{"lua", required_argument, 0, "load lua wsapi app", uwsgi_opt_set_str, &ulua.filename, 0},
{"lua-load", required_argument, 0, "load a lua file", uwsgi_opt_add_string_list, &ulua.load, 0},
{"lua-shell", no_argument, 0, "run the lua interactive shell (debug.debug())", uwsgi_opt_luashell, NULL, 0},
{"luashell", no_argument, 0, "run the lua interactive shell (debug.debug())", uwsgi_opt_luashell, NULL, 0},
{0, 0, 0, 0},
@@ -69,10 +87,10 @@ static int uwsgi_api_register_rpc(lua_State *L) {
lua_pushvalue(L, 2);
func = luaL_ref(L, LUA_REGISTRYINDEX);
uwsgi_log("registered function %d in global table\n", func);
uwsgi_log("registered function %d in Lua global table\n", func);
lfunc = func;
if (uwsgi_register_rpc((char *)name, 6, 0, (void *) lfunc)) {
if (uwsgi_register_rpc((char *)name, &lua_plugin, 0, (void *) lfunc)) {
lua_pushnil(L);
}
else {
@@ -260,7 +278,7 @@ static int uwsgi_api_cache_get(lua_State *L) {
if (argc > 1) {
cache = lua_tolstring(L, 2, NULL);
}
value = uwsgi_cache_magic_get((char *)key, keylen, &valsize, (char *)cache);
value = uwsgi_cache_magic_get((char *)key, keylen, &valsize, NULL, (char *)cache);
if (value) {
lua_pushlstring(L, value, valsize);
free(value);
@@ -345,6 +363,7 @@ static const luaL_reg uwsgi_api[] = {
{"lock", uwsgi_api_lock},
{"unlock", uwsgi_api_unlock},
{NULL, NULL}
};
@@ -387,36 +406,51 @@ static int uwsgi_lua_init(){
static void uwsgi_lua_app() {
int i;
if (ulua.filename) {
if (!ulua.filename && !ulua.load && !ulua.shell) return;
for(i=0;i<uwsgi.cores;i++) {
ulua.L[i] = luaL_newstate();
luaL_openlibs(ulua.L[i]);
luaL_register(ulua.L[i], "uwsgi", uwsgi_api);
if (luaL_loadfile(ulua.L[i], ulua.filename)) {
uwsgi_log("unable to load file %s: %s\n", ulua.filename, lua_tostring(ulua.L[i], -1));
exit(1);
lua_pushstring(ulua.L[i], UWSGI_VERSION);
lua_setfield(ulua.L[i], -2, "version");
struct uwsgi_string_list *usl = ulua.load;
while(usl) {
if (luaL_dofile(ulua.L[i], usl->value)) {
uwsgi_log("unable to load Lua file %s: %s\n", usl->value, lua_tostring(ulua.L[i], -1));
exit(1);
}
usl = usl->next;
}
if (ulua.filename) {
if (luaL_loadfile(ulua.L[i], ulua.filename)) {
uwsgi_log("unable to load Lua file %s: %s\n", ulua.filename, lua_tostring(ulua.L[i], -1));
exit(1);
}
// use a pcall
//lua_call(ulua.L[i], 0, 1);
if (lua_pcall(ulua.L[i], 0, 1, 0) != 0) {
uwsgi_log("%s\n", lua_tostring(ulua.L[i], -1));
exit(1);
}
// use a pcall
//lua_call(ulua.L[i], 0, 1);
if (lua_pcall(ulua.L[i], 0, 1, 0) != 0) {
uwsgi_log("%s\n", lua_tostring(ulua.L[i], -1));
exit(1);
}
// if the loaded lua app returns as a table, fetch the
// run function.
if (lua_istable(ulua.L[i], 2)) {
lua_pushstring(ulua.L[i], "run" );
lua_gettable(ulua.L[i], 2);
lua_replace(ulua.L[i], 2);
}
// if the loaded lua app returns as a table, fetch the
// run function.
if (lua_istable(ulua.L[i], 2)) {
lua_pushstring(ulua.L[i], "run" );
lua_gettable(ulua.L[i], 2);
lua_replace(ulua.L[i], 2);
}
if (! lua_isfunction(ulua.L[i], 2)) {
uwsgi_log("Can't find WSAPI entry point (no function, nor a table with function'run').\n");
exit(1);
if (! lua_isfunction(ulua.L[i], 2)) {
uwsgi_log("Can't find WSAPI entry point (no function, nor a table with function'run').\n");
exit(1);
}
}
}
}
}
@@ -665,13 +699,119 @@ static uint16_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t a
#endif
if (sl <= 0xffff) {
memcpy(buffer, sv, sl);
lua_pop(L, 1);
return sl;
}
lua_pop(L, 1);
return 0;
}
static void uwsgi_lua_configurator_array(lua_State *L) {
int i;
int n = luaL_getn(L, -3);
for(i=1;i<=n;i++) {
lua_rawgeti(L, 1, i);
if (lua_istable(L, -1)) {
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
char *key = uwsgi_str((char *)lua_tostring(L, -2));
char *value = uwsgi_str((char *)lua_tostring(L, -1));
add_exported_option(key, value, 0);
lua_pop(L, 1);
}
}
}
}
static void uwsgi_lua_configurator(char *filename, char *magic_table[]) {
size_t len = 0;
uwsgi_log_initial("[uWSGI] getting Lua configuration from %s\n", filename);
char *code = uwsgi_open_and_read(filename, &len, 1, magic_table);
lua_State *L = luaL_newstate();
if (!L) {
uwsgi_log("unable to initialize Lua state for configuration\n");
exit(1);
}
luaL_openlibs(L);
if (luaL_dostring(L, code) != 0) {
uwsgi_log("error running Lua configurator: %s\n", lua_tostring(L, -1));
exit(1);
}
free(code);
if (!lua_istable(L, -1)) {
uwsgi_log("Lua configurator has to return a table !!!\n");
exit(1);
}
lua_pushnil(L);
// we always use uwsgi_str to avoid GC destroying our strings
// and to be able to call lua_close at the end
while (lua_next(L, -2) != 0) {
// array ?
if (lua_isnumber(L, -2)) {
uwsgi_lua_configurator_array(L);
break;
}
// dictionary
else {
char *key = uwsgi_str((char *)lua_tostring(L, -2));
if (lua_istable(L, -1)) {
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
char *value = uwsgi_str((char *)lua_tostring(L, -1));
add_exported_option(key, value, 0);
lua_pop(L, 1);
}
}
else {
char *value = uwsgi_str((char *)lua_tostring(L, -1));
add_exported_option(key, value, 0);
}
}
lua_pop(L, 1);
}
// this will destroy the whole Lua state
lua_close(L);
}
static void uwsgi_register_lua_features() {
uwsgi_register_configurator(".lua", uwsgi_lua_configurator);
}
static void uwsgi_lua_hijack(void) {
if (ulua.shell && uwsgi.mywid == 1) {
uwsgi.workers[uwsgi.mywid].hijacked = 1;
uwsgi.workers[uwsgi.mywid].hijacked_count++;
// re-map stdin to stdout and stderr if we are logging to a file
if (uwsgi.logfile) {
if (dup2(0, 1) < 0) {
uwsgi_error("dup2()");
}
if (dup2(0, 2) < 0) {
uwsgi_error("dup2()");
}
}
int ret = -1;
// run in the first state
lua_State *L = ulua.L[0];
lua_getglobal(L, "debug");
lua_getfield(L, -1, "debug");
ret = lua_pcall(L, 0, 0, 0);
if (ret == 0) {
exit(UWSGI_QUIET_CODE);
}
exit(0);
}
}
struct uwsgi_plugin lua_plugin = {
@@ -685,8 +825,11 @@ struct uwsgi_plugin lua_plugin = {
.magic = uwsgi_lua_magic,
.signal_handler = uwsgi_lua_signal_handler,
.hijack_worker = uwsgi_lua_hijack,
.code_string = uwsgi_lua_code_string,
.rpc = uwsgi_lua_rpc,
.on_load = uwsgi_register_lua_features,
};
+11
View File
@@ -0,0 +1,11 @@
#include <uwsgi.h>
/*
a fake plugin used for preloading mongodb library when only available as static.
*/
struct uwsgi_plugin mongodb_plugin = {
.name = "mongodb",
};
+8
View File
@@ -0,0 +1,8 @@
NAME='mongodb'
CFLAGS = []
LDFLAGS = []
LIBS = ['-Wl,-whole-archive', '-lmongoclient', '-Wl,-no-whole-archive', '-lboost_thread', '-lboost_system', '-lboost_filesystem']
GCC_LIST = ['plugin']
+3 -3
View File
@@ -1,4 +1,4 @@
#include "../../uwsgi.h"
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
@@ -29,7 +29,7 @@ struct uwsgi_mongodb_state {
struct iovec iovec[13];
};
ssize_t uwsgi_mongodb_logger(struct uwsgi_logger *ul, char *message, size_t len) {
static ssize_t uwsgi_mongodb_logger(struct uwsgi_logger *ul, char *message, size_t len) {
struct uwsgi_mongodb_state *ums = NULL;
@@ -151,7 +151,7 @@ done:
return ret;
}
void uwsgi_mongodblog_register() {
static void uwsgi_mongodblog_register() {
uwsgi_register_logger("mongodblog", uwsgi_mongodb_logger);
}
+3 -3
View File
@@ -267,7 +267,7 @@ static MonoArray *uwsgi_mono_method_api_CacheGet(MonoString *key, MonoString *ca
c_cache = mono_string_to_utf8(cache);
}
uint64_t vallen = 0 ;
char *value = uwsgi_cache_magic_get(c_key, c_keylen, &vallen, c_cache);
char *value = uwsgi_cache_magic_get(c_key, c_keylen, &vallen, NULL, c_cache);
if (value) {
MonoArray *ret = mono_array_new(mono_domain_get(), umono.byte_class, vallen);
char *buf = mono_array_addr(ret, char, 0);
@@ -540,7 +540,7 @@ static int uwsgi_mono_request(struct wsgi_request *wsgi_req) {
key_len = 0;
}
wsgi_req->app_id = uwsgi_get_app_id(key, key_len, mono_plugin.modifier1);
wsgi_req->app_id = uwsgi_get_app_id(NULL, key, key_len, mono_plugin.modifier1);
// if it is -1, try to load a dynamic app
if (wsgi_req->app_id == -1) {
if (uwsgi.threads > 1) {
@@ -548,7 +548,7 @@ static int uwsgi_mono_request(struct wsgi_request *wsgi_req) {
}
// check if the mean time, something changed
wsgi_req->app_id = uwsgi_get_app_id(key, key_len, mono_plugin.modifier1);
wsgi_req->app_id = uwsgi_get_app_id(NULL, key, key_len, mono_plugin.modifier1);
if (wsgi_req->app_id == -1) {
wsgi_req->app_id = uwsgi_mono_create_app(key, key_len, key, key_len, 0);
+2 -2
View File
@@ -96,7 +96,7 @@ static int sapi_uwsgi_send_headers(sapi_headers_struct *sapi_headers)
}
else {
char *sl = SG(sapi_headers).http_status_line;
uwsgi_response_prepare_headers(wsgi_req, sl, strlen(sl));
uwsgi_response_prepare_headers(wsgi_req, sl + 8 , strlen(sl) - 8);
}
h = zend_llist_get_first_ex(&sapi_headers->headers, &pos);
@@ -309,7 +309,7 @@ PHP_FUNCTION(uwsgi_cache_get) {
RETURN_NULL();
}
char *value = uwsgi_cache_magic_get(key, keylen, &valsize, cache);
char *value = uwsgi_cache_magic_get(key, keylen, &valsize, NULL, cache);
if (value) {
char *ret = estrndup(value, valsize);
free(value);
+1 -1
View File
@@ -17,7 +17,7 @@ try:
except:
pass
CFLAGS = [os.popen(PHPPATH + ' --includes').read().rstrip(), '-Wno-error=sign-compare']
CFLAGS = [os.popen(PHPPATH + ' --includes').read().rstrip(), '-Wno-sign-compare']
LDFLAGS = os.popen(PHPPATH + ' --ldflags').read().rstrip().split()
if ld_run_path:

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