unicorn-heroku 4.3.1.1.gc608.dirty

Sign up to get free protection for your applications and to get access to all the features.
Files changed (247) hide show
  1. data/.CHANGELOG.old +25 -0
  2. data/.document +29 -0
  3. data/.gitignore +24 -0
  4. data/.mailmap +26 -0
  5. data/.wrongdoc.yml +10 -0
  6. data/Application_Timeouts +77 -0
  7. data/CONTRIBUTORS +35 -0
  8. data/COPYING +674 -0
  9. data/DESIGN +97 -0
  10. data/Documentation/.gitignore +5 -0
  11. data/Documentation/GNUmakefile +30 -0
  12. data/Documentation/unicorn.1.txt +174 -0
  13. data/Documentation/unicorn_rails.1.txt +175 -0
  14. data/FAQ +53 -0
  15. data/GIT-VERSION-GEN +40 -0
  16. data/GNUmakefile +294 -0
  17. data/HACKING +134 -0
  18. data/ISSUES +36 -0
  19. data/KNOWN_ISSUES +79 -0
  20. data/LICENSE +64 -0
  21. data/Links +56 -0
  22. data/PHILOSOPHY +145 -0
  23. data/README +154 -0
  24. data/Rakefile +97 -0
  25. data/SIGNALS +114 -0
  26. data/Sandbox +96 -0
  27. data/TODO +5 -0
  28. data/TUNING +98 -0
  29. data/bin/unicorn +121 -0
  30. data/bin/unicorn_rails +209 -0
  31. data/examples/big_app_gc.rb +2 -0
  32. data/examples/echo.ru +27 -0
  33. data/examples/git.ru +13 -0
  34. data/examples/init.sh +74 -0
  35. data/examples/logger_mp_safe.rb +25 -0
  36. data/examples/logrotate.conf +29 -0
  37. data/examples/nginx.conf +156 -0
  38. data/examples/unicorn.conf.minimal.rb +13 -0
  39. data/examples/unicorn.conf.rb +94 -0
  40. data/ext/unicorn_http/CFLAGS +13 -0
  41. data/ext/unicorn_http/c_util.h +124 -0
  42. data/ext/unicorn_http/common_field_optimization.h +111 -0
  43. data/ext/unicorn_http/ext_help.h +86 -0
  44. data/ext/unicorn_http/extconf.rb +10 -0
  45. data/ext/unicorn_http/global_variables.h +97 -0
  46. data/ext/unicorn_http/httpdate.c +82 -0
  47. data/ext/unicorn_http/unicorn_http.rl +1036 -0
  48. data/ext/unicorn_http/unicorn_http_common.rl +76 -0
  49. data/lib/unicorn.rb +107 -0
  50. data/lib/unicorn/app/exec_cgi.rb +154 -0
  51. data/lib/unicorn/app/inetd.rb +109 -0
  52. data/lib/unicorn/app/old_rails.rb +35 -0
  53. data/lib/unicorn/app/old_rails/static.rb +59 -0
  54. data/lib/unicorn/cgi_wrapper.rb +147 -0
  55. data/lib/unicorn/configurator.rb +630 -0
  56. data/lib/unicorn/const.rb +40 -0
  57. data/lib/unicorn/http_request.rb +77 -0
  58. data/lib/unicorn/http_response.rb +45 -0
  59. data/lib/unicorn/http_server.rb +744 -0
  60. data/lib/unicorn/launcher.rb +62 -0
  61. data/lib/unicorn/oob_gc.rb +71 -0
  62. data/lib/unicorn/preread_input.rb +33 -0
  63. data/lib/unicorn/socket_helper.rb +208 -0
  64. data/lib/unicorn/ssl_client.rb +11 -0
  65. data/lib/unicorn/ssl_configurator.rb +104 -0
  66. data/lib/unicorn/ssl_server.rb +42 -0
  67. data/lib/unicorn/stream_input.rb +149 -0
  68. data/lib/unicorn/tee_input.rb +126 -0
  69. data/lib/unicorn/tmpio.rb +29 -0
  70. data/lib/unicorn/util.rb +68 -0
  71. data/lib/unicorn/worker.rb +88 -0
  72. data/local.mk.sample +59 -0
  73. data/script/isolate_for_tests +50 -0
  74. data/setup.rb +1586 -0
  75. data/t/.gitignore +5 -0
  76. data/t/GNUmakefile +82 -0
  77. data/t/README +42 -0
  78. data/t/bin/content-md5-put +36 -0
  79. data/t/bin/sha1sum.rb +17 -0
  80. data/t/bin/unused_listen +40 -0
  81. data/t/bin/utee +12 -0
  82. data/t/broken-app.ru +12 -0
  83. data/t/detach.ru +11 -0
  84. data/t/env.ru +3 -0
  85. data/t/heartbeat-timeout.ru +12 -0
  86. data/t/my-tap-lib.sh +201 -0
  87. data/t/oob_gc.ru +21 -0
  88. data/t/oob_gc_path.ru +21 -0
  89. data/t/pid.ru +3 -0
  90. data/t/preread_input.ru +17 -0
  91. data/t/rack-input-tests.ru +21 -0
  92. data/t/rails3-app/.gitignore +4 -0
  93. data/t/rails3-app/Gemfile +26 -0
  94. data/t/rails3-app/Rakefile +10 -0
  95. data/t/rails3-app/app/controllers/application_controller.rb +4 -0
  96. data/t/rails3-app/app/helpers/application_helper.rb +2 -0
  97. data/t/rails3-app/app/views/layouts/application.html.erb +14 -0
  98. data/t/rails3-app/config.ru +4 -0
  99. data/t/rails3-app/config/application.rb +46 -0
  100. data/t/rails3-app/config/boot.rb +6 -0
  101. data/t/rails3-app/config/database.yml +22 -0
  102. data/t/rails3-app/config/environment.rb +5 -0
  103. data/t/rails3-app/config/environments/development.rb +19 -0
  104. data/t/rails3-app/config/environments/production.rb +42 -0
  105. data/t/rails3-app/config/environments/test.rb +32 -0
  106. data/t/rails3-app/config/initializers/backtrace_silencers.rb +7 -0
  107. data/t/rails3-app/config/initializers/inflections.rb +10 -0
  108. data/t/rails3-app/config/initializers/mime_types.rb +5 -0
  109. data/t/rails3-app/config/initializers/secret_token.rb +7 -0
  110. data/t/rails3-app/config/initializers/session_store.rb +8 -0
  111. data/t/rails3-app/config/locales/en.yml +5 -0
  112. data/t/rails3-app/config/routes.rb +58 -0
  113. data/t/rails3-app/db/seeds.rb +7 -0
  114. data/t/rails3-app/doc/README_FOR_APP +2 -0
  115. data/t/rails3-app/lib/tasks/.gitkeep +0 -0
  116. data/t/rails3-app/public/404.html +1 -0
  117. data/t/rails3-app/public/500.html +1 -0
  118. data/t/rails3-app/public/x.txt +1 -0
  119. data/t/rails3-app/script/rails +9 -0
  120. data/t/rails3-app/test/performance/browsing_test.rb +9 -0
  121. data/t/rails3-app/test/test_helper.rb +13 -0
  122. data/t/rails3-app/vendor/plugins/.gitkeep +0 -0
  123. data/t/sslgen.sh +71 -0
  124. data/t/t0000-http-basic.sh +50 -0
  125. data/t/t0001-reload-bad-config.sh +53 -0
  126. data/t/t0002-config-conflict.sh +49 -0
  127. data/t/t0002-parser-error.sh +94 -0
  128. data/t/t0003-working_directory.sh +51 -0
  129. data/t/t0004-heartbeat-timeout.sh +69 -0
  130. data/t/t0004-working_directory_broken.sh +24 -0
  131. data/t/t0005-working_directory_app.rb.sh +37 -0
  132. data/t/t0006-reopen-logs.sh +83 -0
  133. data/t/t0006.ru +13 -0
  134. data/t/t0007-working_directory_no_embed_cli.sh +44 -0
  135. data/t/t0008-back_out_of_upgrade.sh +110 -0
  136. data/t/t0009-broken-app.sh +56 -0
  137. data/t/t0009-winch_ttin.sh +59 -0
  138. data/t/t0010-reap-logging.sh +55 -0
  139. data/t/t0011-active-unix-socket.sh +79 -0
  140. data/t/t0012-reload-empty-config.sh +85 -0
  141. data/t/t0013-rewindable-input-false.sh +24 -0
  142. data/t/t0013.ru +12 -0
  143. data/t/t0014-rewindable-input-true.sh +24 -0
  144. data/t/t0014.ru +12 -0
  145. data/t/t0015-configurator-internals.sh +25 -0
  146. data/t/t0016-trust-x-forwarded-false.sh +30 -0
  147. data/t/t0017-trust-x-forwarded-true.sh +30 -0
  148. data/t/t0018-write-on-close.sh +23 -0
  149. data/t/t0019-max_header_len.sh +49 -0
  150. data/t/t0020-at_exit-handler.sh +49 -0
  151. data/t/t0021-process_detach.sh +29 -0
  152. data/t/t0100-rack-input-tests.sh +124 -0
  153. data/t/t0116-client_body_buffer_size.sh +80 -0
  154. data/t/t0116.ru +16 -0
  155. data/t/t0300-rails3-basic.sh +28 -0
  156. data/t/t0301-rails3-missing-config-ru.sh +33 -0
  157. data/t/t0302-rails3-alt-working_directory.sh +32 -0
  158. data/t/t0303-rails3-alt-working_directory_config.ru.sh +56 -0
  159. data/t/t0304-rails3-alt-working_directory_no_embed_cli.sh +52 -0
  160. data/t/t0600-https-server-basic.sh +48 -0
  161. data/t/t9000-preread-input.sh +48 -0
  162. data/t/t9001-oob_gc.sh +47 -0
  163. data/t/t9002-oob_gc-path.sh +75 -0
  164. data/t/test-lib.sh +113 -0
  165. data/t/test-rails3.sh +27 -0
  166. data/t/write-on-close.ru +11 -0
  167. data/test/aggregate.rb +15 -0
  168. data/test/benchmark/README +50 -0
  169. data/test/benchmark/dd.ru +18 -0
  170. data/test/benchmark/stack.ru +8 -0
  171. data/test/exec/README +5 -0
  172. data/test/exec/test_exec.rb +1055 -0
  173. data/test/rails/app-1.2.3/.gitignore +2 -0
  174. data/test/rails/app-1.2.3/Rakefile +7 -0
  175. data/test/rails/app-1.2.3/app/controllers/application.rb +6 -0
  176. data/test/rails/app-1.2.3/app/controllers/foo_controller.rb +36 -0
  177. data/test/rails/app-1.2.3/app/helpers/application_helper.rb +4 -0
  178. data/test/rails/app-1.2.3/config/boot.rb +11 -0
  179. data/test/rails/app-1.2.3/config/database.yml +12 -0
  180. data/test/rails/app-1.2.3/config/environment.rb +13 -0
  181. data/test/rails/app-1.2.3/config/environments/development.rb +9 -0
  182. data/test/rails/app-1.2.3/config/environments/production.rb +5 -0
  183. data/test/rails/app-1.2.3/config/routes.rb +6 -0
  184. data/test/rails/app-1.2.3/db/.gitignore +0 -0
  185. data/test/rails/app-1.2.3/public/404.html +1 -0
  186. data/test/rails/app-1.2.3/public/500.html +1 -0
  187. data/test/rails/app-2.0.2/.gitignore +2 -0
  188. data/test/rails/app-2.0.2/Rakefile +7 -0
  189. data/test/rails/app-2.0.2/app/controllers/application.rb +4 -0
  190. data/test/rails/app-2.0.2/app/controllers/foo_controller.rb +36 -0
  191. data/test/rails/app-2.0.2/app/helpers/application_helper.rb +4 -0
  192. data/test/rails/app-2.0.2/config/boot.rb +11 -0
  193. data/test/rails/app-2.0.2/config/database.yml +12 -0
  194. data/test/rails/app-2.0.2/config/environment.rb +17 -0
  195. data/test/rails/app-2.0.2/config/environments/development.rb +8 -0
  196. data/test/rails/app-2.0.2/config/environments/production.rb +5 -0
  197. data/test/rails/app-2.0.2/config/routes.rb +6 -0
  198. data/test/rails/app-2.0.2/db/.gitignore +0 -0
  199. data/test/rails/app-2.0.2/public/404.html +1 -0
  200. data/test/rails/app-2.0.2/public/500.html +1 -0
  201. data/test/rails/app-2.1.2/.gitignore +2 -0
  202. data/test/rails/app-2.1.2/Rakefile +7 -0
  203. data/test/rails/app-2.1.2/app/controllers/application.rb +4 -0
  204. data/test/rails/app-2.1.2/app/controllers/foo_controller.rb +36 -0
  205. data/test/rails/app-2.1.2/app/helpers/application_helper.rb +4 -0
  206. data/test/rails/app-2.1.2/config/boot.rb +111 -0
  207. data/test/rails/app-2.1.2/config/database.yml +12 -0
  208. data/test/rails/app-2.1.2/config/environment.rb +17 -0
  209. data/test/rails/app-2.1.2/config/environments/development.rb +7 -0
  210. data/test/rails/app-2.1.2/config/environments/production.rb +5 -0
  211. data/test/rails/app-2.1.2/config/routes.rb +6 -0
  212. data/test/rails/app-2.1.2/db/.gitignore +0 -0
  213. data/test/rails/app-2.1.2/public/404.html +1 -0
  214. data/test/rails/app-2.1.2/public/500.html +1 -0
  215. data/test/rails/app-2.2.2/.gitignore +2 -0
  216. data/test/rails/app-2.2.2/Rakefile +7 -0
  217. data/test/rails/app-2.2.2/app/controllers/application.rb +4 -0
  218. data/test/rails/app-2.2.2/app/controllers/foo_controller.rb +36 -0
  219. data/test/rails/app-2.2.2/app/helpers/application_helper.rb +4 -0
  220. data/test/rails/app-2.2.2/config/boot.rb +111 -0
  221. data/test/rails/app-2.2.2/config/database.yml +12 -0
  222. data/test/rails/app-2.2.2/config/environment.rb +17 -0
  223. data/test/rails/app-2.2.2/config/environments/development.rb +7 -0
  224. data/test/rails/app-2.2.2/config/environments/production.rb +5 -0
  225. data/test/rails/app-2.2.2/config/routes.rb +6 -0
  226. data/test/rails/app-2.2.2/db/.gitignore +0 -0
  227. data/test/rails/app-2.2.2/public/404.html +1 -0
  228. data/test/rails/app-2.2.2/public/500.html +1 -0
  229. data/test/rails/test_rails.rb +287 -0
  230. data/test/test_helper.rb +300 -0
  231. data/test/unit/test_configurator.rb +158 -0
  232. data/test/unit/test_droplet.rb +28 -0
  233. data/test/unit/test_http_parser.rb +860 -0
  234. data/test/unit/test_http_parser_ng.rb +716 -0
  235. data/test/unit/test_http_parser_xftrust.rb +38 -0
  236. data/test/unit/test_request.rb +197 -0
  237. data/test/unit/test_response.rb +99 -0
  238. data/test/unit/test_server.rb +289 -0
  239. data/test/unit/test_signals.rb +207 -0
  240. data/test/unit/test_sni_hostnames.rb +47 -0
  241. data/test/unit/test_socket_helper.rb +192 -0
  242. data/test/unit/test_stream_input.rb +204 -0
  243. data/test/unit/test_tee_input.rb +296 -0
  244. data/test/unit/test_upload.rb +306 -0
  245. data/test/unit/test_util.rb +100 -0
  246. data/unicorn-heroku.gemspec +44 -0
  247. metadata +426 -0
@@ -0,0 +1,13 @@
1
+ # Minimal sample configuration file for Unicorn (not Rack) when used
2
+ # with daemonization (unicorn -D) started in your working directory.
3
+ #
4
+ # See http://unicorn.bogomips.org/Unicorn/Configurator.html for complete
5
+ # documentation.
6
+ # See also http://unicorn.bogomips.org/examples/unicorn.conf.rb for
7
+ # a more verbose configuration using more features.
8
+
9
+ listen 2007 # by default Unicorn listens on port 8080
10
+ worker_processes 2 # this should be >= nr_cpus
11
+ pid "/path/to/app/shared/pids/unicorn.pid"
12
+ stderr_path "/path/to/app/shared/log/unicorn.log"
13
+ stdout_path "/path/to/app/shared/log/unicorn.log"
@@ -0,0 +1,94 @@
1
+ # Sample verbose configuration file for Unicorn (not Rack)
2
+ #
3
+ # This configuration file documents many features of Unicorn
4
+ # that may not be needed for some applications. See
5
+ # http://unicorn.bogomips.org/examples/unicorn.conf.minimal.rb
6
+ # for a much simpler configuration file.
7
+ #
8
+ # See http://unicorn.bogomips.org/Unicorn/Configurator.html for complete
9
+ # documentation.
10
+
11
+ # Use at least one worker per core if you're on a dedicated server,
12
+ # more will usually help for _short_ waits on databases/caches.
13
+ worker_processes 4
14
+
15
+ # Since Unicorn is never exposed to outside clients, it does not need to
16
+ # run on the standard HTTP port (80), there is no reason to start Unicorn
17
+ # as root unless it's from system init scripts.
18
+ # If running the master process as root and the workers as an unprivileged
19
+ # user, do this to switch euid/egid in the workers (also chowns logs):
20
+ # user "unprivileged_user", "unprivileged_group"
21
+
22
+ # Help ensure your application will always spawn in the symlinked
23
+ # "current" directory that Capistrano sets up.
24
+ working_directory "/path/to/app/current" # available in 0.94.0+
25
+
26
+ # listen on both a Unix domain socket and a TCP port,
27
+ # we use a shorter backlog for quicker failover when busy
28
+ listen "/tmp/.sock", :backlog => 64
29
+ listen 8080, :tcp_nopush => true
30
+
31
+ # nuke workers after 30 seconds instead of 60 seconds (the default)
32
+ timeout 30
33
+
34
+ # feel free to point this anywhere accessible on the filesystem
35
+ pid "/path/to/app/shared/pids/unicorn.pid"
36
+
37
+ # By default, the Unicorn logger will write to stderr.
38
+ # Additionally, ome applications/frameworks log to stderr or stdout,
39
+ # so prevent them from going to /dev/null when daemonized here:
40
+ stderr_path "/path/to/app/shared/log/unicorn.stderr.log"
41
+ stdout_path "/path/to/app/shared/log/unicorn.stdout.log"
42
+
43
+ # combine Ruby 2.0.0dev or REE with "preload_app true" for memory savings
44
+ # http://rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
45
+ preload_app true
46
+ GC.respond_to?(:copy_on_write_friendly=) and
47
+ GC.copy_on_write_friendly = true
48
+
49
+ before_fork do |server, worker|
50
+ # the following is highly recomended for Rails + "preload_app true"
51
+ # as there's no need for the master process to hold a connection
52
+ defined?(ActiveRecord::Base) and
53
+ ActiveRecord::Base.connection.disconnect!
54
+
55
+ # The following is only recommended for memory/DB-constrained
56
+ # installations. It is not needed if your system can house
57
+ # twice as many worker_processes as you have configured.
58
+ #
59
+ # # This allows a new master process to incrementally
60
+ # # phase out the old master process with SIGTTOU to avoid a
61
+ # # thundering herd (especially in the "preload_app false" case)
62
+ # # when doing a transparent upgrade. The last worker spawned
63
+ # # will then kill off the old master process with a SIGTERM.
64
+ # old_pid = "#{server.config[:pid]}.oldbin"
65
+ # if old_pid != server.pid
66
+ # begin
67
+ # sig = (worker.nr + 1) >= server.worker_processes ? :TERM : :TTOU
68
+ # Process.kill(sig, File.read(old_pid).to_i)
69
+ # rescue Errno::ENOENT, Errno::ESRCH
70
+ # end
71
+ # end
72
+ #
73
+ # Throttle the master from forking too quickly by sleeping. Due
74
+ # to the implementation of standard Unix signal handlers, this
75
+ # helps (but does not completely) prevent identical, repeated signals
76
+ # from being lost when the receiving process is busy.
77
+ # sleep 1
78
+ end
79
+
80
+ after_fork do |server, worker|
81
+ # per-process listener ports for debugging/admin/migrations
82
+ # addr = "127.0.0.1:#{9293 + worker.nr}"
83
+ # server.listen(addr, :tries => -1, :delay => 5, :tcp_nopush => true)
84
+
85
+ # the following is *required* for Rails + "preload_app true",
86
+ defined?(ActiveRecord::Base) and
87
+ ActiveRecord::Base.establish_connection
88
+
89
+ # if preload_app is true, then you may also want to check and
90
+ # restart any other shared sockets/descriptors such as Memcached,
91
+ # and Redis. TokyoCabinet file handles are safe to reuse
92
+ # between any number of forked children (assuming your kernel
93
+ # correctly implements pread()/pwrite() system calls)
94
+ end
@@ -0,0 +1,13 @@
1
+ # CFLAGS used for development (gcc-dependent)
2
+ # source this file if you want/need them
3
+ CFLAGS=
4
+ CFLAGS="$CFLAGS -Wall"
5
+ CFLAGS="$CFLAGS -Wwrite-strings"
6
+ CFLAGS="$CFLAGS -Wdeclaration-after-statement"
7
+ CFLAGS="$CFLAGS -Wcast-qual"
8
+ CFLAGS="$CFLAGS -Wstrict-prototypes"
9
+ CFLAGS="$CFLAGS -Wshadow"
10
+ CFLAGS="$CFLAGS -Wextra"
11
+ CFLAGS="$CFLAGS -Wno-deprecated-declarations"
12
+ CFLAGS="$CFLAGS -Waggregate-return"
13
+ CFLAGS="$CFLAGS -Wchar-subscripts"
@@ -0,0 +1,124 @@
1
+ /*
2
+ * Generic C functions and macros go here, there are no dependencies
3
+ * on Unicorn internal structures or the Ruby C API in here.
4
+ */
5
+
6
+ #ifndef UH_util_h
7
+ #define UH_util_h
8
+
9
+ #include <unistd.h>
10
+ #include <assert.h>
11
+
12
+ #define MIN(a,b) (a < b ? a : b)
13
+ #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
14
+
15
+ #ifndef SIZEOF_OFF_T
16
+ # define SIZEOF_OFF_T 4
17
+ # warning SIZEOF_OFF_T not defined, guessing 4. Did you run extconf.rb?
18
+ #endif
19
+
20
+ #if SIZEOF_OFF_T == 4
21
+ # define UH_OFF_T_MAX 0x7fffffff
22
+ #elif SIZEOF_OFF_T == 8
23
+ # if SIZEOF_LONG == 4
24
+ # define UH_OFF_T_MAX 0x7fffffffffffffffLL
25
+ # else
26
+ # define UH_OFF_T_MAX 0x7fffffffffffffff
27
+ # endif
28
+ #else
29
+ # error off_t size unknown for this platform!
30
+ #endif /* SIZEOF_OFF_T check */
31
+
32
+ /*
33
+ * ragel enforces fpc as a const, and merely casting can make picky
34
+ * compilers unhappy, so we have this little helper do our dirty work
35
+ */
36
+ static inline void *deconst(const void *in)
37
+ {
38
+ union { const void *in; void *out; } tmp;
39
+
40
+ tmp.in = in;
41
+
42
+ return tmp.out;
43
+ }
44
+
45
+ /*
46
+ * capitalizes all lower-case ASCII characters and converts dashes
47
+ * to underscores for HTTP headers. Locale-agnostic.
48
+ */
49
+ static void snake_upcase_char(char *c)
50
+ {
51
+ if (*c >= 'a' && *c <= 'z')
52
+ *c &= ~0x20;
53
+ else if (*c == '-')
54
+ *c = '_';
55
+ }
56
+
57
+ /* Downcases a single ASCII character. Locale-agnostic. */
58
+ static void downcase_char(char *c)
59
+ {
60
+ if (*c >= 'A' && *c <= 'Z')
61
+ *c |= 0x20;
62
+ }
63
+
64
+ static int hexchar2int(int xdigit)
65
+ {
66
+ if (xdigit >= 'A' && xdigit <= 'F')
67
+ return xdigit - 'A' + 10;
68
+ if (xdigit >= 'a' && xdigit <= 'f')
69
+ return xdigit - 'a' + 10;
70
+
71
+ /* Ragel already does runtime range checking for us in Unicorn: */
72
+ assert(xdigit >= '0' && xdigit <= '9' && "invalid digit character");
73
+
74
+ return xdigit - '0';
75
+ }
76
+
77
+ /*
78
+ * multiplies +i+ by +base+ and increments the result by the parsed
79
+ * integer value of +xdigit+. +xdigit+ is a character byte
80
+ * representing a number the range of 0..(base-1)
81
+ * returns the new value of +i+ on success
82
+ * returns -1 on errors (including overflow)
83
+ */
84
+ static off_t step_incr(off_t i, int xdigit, const int base)
85
+ {
86
+ static const off_t max = UH_OFF_T_MAX;
87
+ const off_t next_max = (max - (max % base)) / base;
88
+ off_t offset = hexchar2int(xdigit);
89
+
90
+ if (offset > (base - 1))
91
+ return -1;
92
+ if (i > next_max)
93
+ return -1;
94
+ i *= base;
95
+
96
+ if ((offset > (base - 1)) || ((max - i) < offset))
97
+ return -1;
98
+
99
+ return i + offset;
100
+ }
101
+
102
+ /*
103
+ * parses a non-negative length according to base-10 and
104
+ * returns it as an off_t value. Returns -1 on errors
105
+ * (including overflow).
106
+ */
107
+ static off_t parse_length(const char *value, size_t length)
108
+ {
109
+ off_t rv;
110
+
111
+ for (rv = 0; length-- && rv >= 0; ++value) {
112
+ if (*value >= '0' && *value <= '9')
113
+ rv = step_incr(rv, *value, 10);
114
+ else
115
+ return -1;
116
+ }
117
+
118
+ return rv;
119
+ }
120
+
121
+ #define CONST_MEM_EQ(const_p, buf, len) \
122
+ ((sizeof(const_p) - 1) == len && !memcmp(const_p, buf, sizeof(const_p) - 1))
123
+
124
+ #endif /* UH_util_h */
@@ -0,0 +1,111 @@
1
+ #ifndef common_field_optimization
2
+ #define common_field_optimization
3
+ #include "ruby.h"
4
+ #include "c_util.h"
5
+
6
+ struct common_field {
7
+ const signed long len;
8
+ const char *name;
9
+ VALUE value;
10
+ };
11
+
12
+ /*
13
+ * A list of common HTTP headers we expect to receive.
14
+ * This allows us to avoid repeatedly creating identical string
15
+ * objects to be used with rb_hash_aset().
16
+ */
17
+ static struct common_field common_http_fields[] = {
18
+ # define f(N) { (sizeof(N) - 1), N, Qnil }
19
+ f("ACCEPT"),
20
+ f("ACCEPT_CHARSET"),
21
+ f("ACCEPT_ENCODING"),
22
+ f("ACCEPT_LANGUAGE"),
23
+ f("ALLOW"),
24
+ f("AUTHORIZATION"),
25
+ f("CACHE_CONTROL"),
26
+ f("CONNECTION"),
27
+ f("CONTENT_ENCODING"),
28
+ f("CONTENT_LENGTH"),
29
+ f("CONTENT_TYPE"),
30
+ f("COOKIE"),
31
+ f("DATE"),
32
+ f("EXPECT"),
33
+ f("FROM"),
34
+ f("HOST"),
35
+ f("IF_MATCH"),
36
+ f("IF_MODIFIED_SINCE"),
37
+ f("IF_NONE_MATCH"),
38
+ f("IF_RANGE"),
39
+ f("IF_UNMODIFIED_SINCE"),
40
+ f("KEEP_ALIVE"), /* Firefox sends this */
41
+ f("MAX_FORWARDS"),
42
+ f("PRAGMA"),
43
+ f("PROXY_AUTHORIZATION"),
44
+ f("RANGE"),
45
+ f("REFERER"),
46
+ f("TE"),
47
+ f("TRAILER"),
48
+ f("TRANSFER_ENCODING"),
49
+ f("UPGRADE"),
50
+ f("USER_AGENT"),
51
+ f("VIA"),
52
+ f("X_FORWARDED_FOR"), /* common for proxies */
53
+ f("X_FORWARDED_PROTO"), /* common for proxies */
54
+ f("X_REAL_IP"), /* common for proxies */
55
+ f("WARNING")
56
+ # undef f
57
+ };
58
+
59
+ #define HTTP_PREFIX "HTTP_"
60
+ #define HTTP_PREFIX_LEN (sizeof(HTTP_PREFIX) - 1)
61
+
62
+ /* this function is not performance-critical, called only at load time */
63
+ static void init_common_fields(void)
64
+ {
65
+ int i;
66
+ struct common_field *cf = common_http_fields;
67
+ char tmp[64];
68
+ memcpy(tmp, HTTP_PREFIX, HTTP_PREFIX_LEN);
69
+
70
+ for(i = ARRAY_SIZE(common_http_fields); --i >= 0; cf++) {
71
+ /* Rack doesn't like certain headers prefixed with "HTTP_" */
72
+ if (!strcmp("CONTENT_LENGTH", cf->name) ||
73
+ !strcmp("CONTENT_TYPE", cf->name)) {
74
+ cf->value = rb_str_new(cf->name, cf->len);
75
+ } else {
76
+ memcpy(tmp + HTTP_PREFIX_LEN, cf->name, cf->len + 1);
77
+ cf->value = rb_str_new(tmp, HTTP_PREFIX_LEN + cf->len);
78
+ }
79
+ cf->value = rb_obj_freeze(cf->value);
80
+ rb_global_variable(&cf->value);
81
+ }
82
+ }
83
+
84
+ /* this function is called for every header set */
85
+ static VALUE find_common_field(const char *field, size_t flen)
86
+ {
87
+ int i;
88
+ struct common_field *cf = common_http_fields;
89
+
90
+ for(i = ARRAY_SIZE(common_http_fields); --i >= 0; cf++) {
91
+ if (cf->len == (long)flen && !memcmp(cf->name, field, flen))
92
+ return cf->value;
93
+ }
94
+ return Qnil;
95
+ }
96
+
97
+ /*
98
+ * We got a strange header that we don't have a memoized value for.
99
+ * Fallback to creating a new string to use as a hash key.
100
+ */
101
+ static VALUE uncommon_field(const char *field, size_t flen)
102
+ {
103
+ VALUE f = rb_str_new(NULL, HTTP_PREFIX_LEN + flen);
104
+ memcpy(RSTRING_PTR(f), HTTP_PREFIX, HTTP_PREFIX_LEN);
105
+ memcpy(RSTRING_PTR(f) + HTTP_PREFIX_LEN, field, flen);
106
+ assert(*(RSTRING_PTR(f) + RSTRING_LEN(f)) == '\0' &&
107
+ "string didn't end with \\0"); /* paranoia */
108
+ return rb_obj_freeze(f);
109
+ }
110
+
111
+ #endif /* common_field_optimization_h */
@@ -0,0 +1,86 @@
1
+ #ifndef ext_help_h
2
+ #define ext_help_h
3
+
4
+ #ifndef RSTRING_PTR
5
+ #define RSTRING_PTR(s) (RSTRING(s)->ptr)
6
+ #endif /* !defined(RSTRING_PTR) */
7
+ #ifndef RSTRING_LEN
8
+ #define RSTRING_LEN(s) (RSTRING(s)->len)
9
+ #endif /* !defined(RSTRING_LEN) */
10
+
11
+ #ifndef HAVE_RB_STR_SET_LEN
12
+ # ifdef RUBINIUS
13
+ # error we should never get here with current Rubinius (1.x)
14
+ # endif
15
+ /* this is taken from Ruby 1.8.7, 1.8.6 may not have it */
16
+ static void rb_18_str_set_len(VALUE str, long len)
17
+ {
18
+ RSTRING(str)->len = len;
19
+ RSTRING(str)->ptr[len] = '\0';
20
+ }
21
+ # define rb_str_set_len(str,len) rb_18_str_set_len(str,len)
22
+ #endif /* !defined(HAVE_RB_STR_SET_LEN) */
23
+
24
+ /* not all Ruby implementations support frozen objects (Rubinius does not) */
25
+ #if defined(OBJ_FROZEN)
26
+ # define assert_frozen(f) assert(OBJ_FROZEN(f) && "unfrozen object")
27
+ #else
28
+ # define assert_frozen(f) do {} while (0)
29
+ #endif /* !defined(OBJ_FROZEN) */
30
+
31
+ #if !defined(OFFT2NUM)
32
+ # if SIZEOF_OFF_T == SIZEOF_LONG
33
+ # define OFFT2NUM(n) LONG2NUM(n)
34
+ # else
35
+ # define OFFT2NUM(n) LL2NUM(n)
36
+ # endif
37
+ #endif /* ! defined(OFFT2NUM) */
38
+
39
+ #if !defined(SIZET2NUM)
40
+ # if SIZEOF_SIZE_T == SIZEOF_LONG
41
+ # define SIZET2NUM(n) ULONG2NUM(n)
42
+ # else
43
+ # define SIZET2NUM(n) ULL2NUM(n)
44
+ # endif
45
+ #endif /* ! defined(SIZET2NUM) */
46
+
47
+ #if !defined(NUM2SIZET)
48
+ # if SIZEOF_SIZE_T == SIZEOF_LONG
49
+ # define NUM2SIZET(n) ((size_t)NUM2ULONG(n))
50
+ # else
51
+ # define NUM2SIZET(n) ((size_t)NUM2ULL(n))
52
+ # endif
53
+ #endif /* ! defined(NUM2SIZET) */
54
+
55
+ #ifndef HAVE_RB_STR_MODIFY
56
+ # define rb_str_modify(x) do {} while (0)
57
+ #endif /* ! defined(HAVE_RB_STR_MODIFY) */
58
+
59
+ static inline int str_cstr_eq(VALUE val, const char *ptr, long len)
60
+ {
61
+ return (RSTRING_LEN(val) == len && !memcmp(ptr, RSTRING_PTR(val), len));
62
+ }
63
+
64
+ #define STR_CSTR_EQ(val, const_str) \
65
+ str_cstr_eq(val, const_str, sizeof(const_str) - 1)
66
+
67
+ /* strcasecmp isn't locale independent */
68
+ static int str_cstr_case_eq(VALUE val, const char *ptr, long len)
69
+ {
70
+ if (RSTRING_LEN(val) == len) {
71
+ const char *v = RSTRING_PTR(val);
72
+
73
+ for (; len--; ++ptr, ++v) {
74
+ if ((*ptr == *v) || (*v >= 'A' && *v <= 'Z' && (*v | 0x20) == *ptr))
75
+ continue;
76
+ return 0;
77
+ }
78
+ return 1;
79
+ }
80
+ return 0;
81
+ }
82
+
83
+ #define STR_CSTR_CASE_EQ(val, const_str) \
84
+ str_cstr_case_eq(val, const_str, sizeof(const_str) - 1)
85
+
86
+ #endif /* ext_help_h */
@@ -0,0 +1,10 @@
1
+ # -*- encoding: binary -*-
2
+ require 'mkmf'
3
+
4
+ have_macro("SIZEOF_OFF_T", "ruby.h") or check_sizeof("off_t", "sys/types.h")
5
+ have_macro("SIZEOF_SIZE_T", "ruby.h") or check_sizeof("size_t", "sys/types.h")
6
+ have_macro("SIZEOF_LONG", "ruby.h") or check_sizeof("long", "sys/types.h")
7
+ have_func("rb_str_set_len", "ruby.h")
8
+ have_func("gmtime_r", "time.h")
9
+
10
+ create_makefile("unicorn_http")