piesync-puma 3.12.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/History.md +1429 -0
  3. data/LICENSE +26 -0
  4. data/README.md +280 -0
  5. data/bin/puma +10 -0
  6. data/bin/puma-wild +31 -0
  7. data/bin/pumactl +12 -0
  8. data/docs/architecture.md +36 -0
  9. data/docs/deployment.md +91 -0
  10. data/docs/images/puma-connection-flow-no-reactor.png +0 -0
  11. data/docs/images/puma-connection-flow.png +0 -0
  12. data/docs/images/puma-general-arch.png +0 -0
  13. data/docs/nginx.md +80 -0
  14. data/docs/plugins.md +28 -0
  15. data/docs/restart.md +39 -0
  16. data/docs/signals.md +96 -0
  17. data/docs/systemd.md +272 -0
  18. data/ext/puma_http11/PumaHttp11Service.java +17 -0
  19. data/ext/puma_http11/ext_help.h +15 -0
  20. data/ext/puma_http11/extconf.rb +15 -0
  21. data/ext/puma_http11/http11_parser.c +1071 -0
  22. data/ext/puma_http11/http11_parser.h +65 -0
  23. data/ext/puma_http11/http11_parser.java.rl +161 -0
  24. data/ext/puma_http11/http11_parser.rl +149 -0
  25. data/ext/puma_http11/http11_parser_common.rl +54 -0
  26. data/ext/puma_http11/io_buffer.c +155 -0
  27. data/ext/puma_http11/mini_ssl.c +494 -0
  28. data/ext/puma_http11/org/jruby/puma/Http11.java +234 -0
  29. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +470 -0
  30. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +352 -0
  31. data/ext/puma_http11/puma_http11.c +500 -0
  32. data/lib/puma.rb +23 -0
  33. data/lib/puma/accept_nonblock.rb +23 -0
  34. data/lib/puma/app/status.rb +74 -0
  35. data/lib/puma/binder.rb +413 -0
  36. data/lib/puma/cli.rb +235 -0
  37. data/lib/puma/client.rb +480 -0
  38. data/lib/puma/cluster.rb +531 -0
  39. data/lib/puma/commonlogger.rb +108 -0
  40. data/lib/puma/compat.rb +14 -0
  41. data/lib/puma/configuration.rb +361 -0
  42. data/lib/puma/const.rb +239 -0
  43. data/lib/puma/control_cli.rb +264 -0
  44. data/lib/puma/convenient.rb +25 -0
  45. data/lib/puma/daemon_ext.rb +33 -0
  46. data/lib/puma/delegation.rb +13 -0
  47. data/lib/puma/detect.rb +15 -0
  48. data/lib/puma/dsl.rb +518 -0
  49. data/lib/puma/events.rb +153 -0
  50. data/lib/puma/io_buffer.rb +9 -0
  51. data/lib/puma/java_io_buffer.rb +47 -0
  52. data/lib/puma/jruby_restart.rb +84 -0
  53. data/lib/puma/launcher.rb +433 -0
  54. data/lib/puma/minissl.rb +285 -0
  55. data/lib/puma/null_io.rb +44 -0
  56. data/lib/puma/plugin.rb +117 -0
  57. data/lib/puma/plugin/tmp_restart.rb +34 -0
  58. data/lib/puma/rack/backports/uri/common_193.rb +33 -0
  59. data/lib/puma/rack/builder.rb +299 -0
  60. data/lib/puma/rack/urlmap.rb +91 -0
  61. data/lib/puma/rack_default.rb +7 -0
  62. data/lib/puma/reactor.rb +347 -0
  63. data/lib/puma/runner.rb +184 -0
  64. data/lib/puma/server.rb +1072 -0
  65. data/lib/puma/single.rb +123 -0
  66. data/lib/puma/state_file.rb +31 -0
  67. data/lib/puma/tcp_logger.rb +41 -0
  68. data/lib/puma/thread_pool.rb +346 -0
  69. data/lib/puma/util.rb +129 -0
  70. data/lib/rack/handler/puma.rb +115 -0
  71. data/tools/jungle/README.md +19 -0
  72. data/tools/jungle/init.d/README.md +61 -0
  73. data/tools/jungle/init.d/puma +421 -0
  74. data/tools/jungle/init.d/run-puma +18 -0
  75. data/tools/jungle/rc.d/README.md +74 -0
  76. data/tools/jungle/rc.d/puma +61 -0
  77. data/tools/jungle/rc.d/puma.conf +10 -0
  78. data/tools/jungle/upstart/README.md +61 -0
  79. data/tools/jungle/upstart/puma-manager.conf +31 -0
  80. data/tools/jungle/upstart/puma.conf +69 -0
  81. data/tools/trickletest.rb +45 -0
  82. metadata +131 -0
@@ -0,0 +1,23 @@
1
+ # Standard libraries
2
+ require 'socket'
3
+ require 'tempfile'
4
+ require 'time'
5
+ require 'etc'
6
+ require 'uri'
7
+ require 'stringio'
8
+
9
+ require 'thread'
10
+
11
+ module Puma
12
+ autoload :Const, 'puma/const'
13
+ autoload :Server, 'puma/server'
14
+ autoload :Launcher, 'puma/launcher'
15
+
16
+ def self.stats_object=(val)
17
+ @get_stats = val
18
+ end
19
+
20
+ def self.stats
21
+ @get_stats.stats
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ require 'openssl'
2
+
3
+ module OpenSSL
4
+ module SSL
5
+ class SSLServer
6
+ unless public_method_defined? :accept_nonblock
7
+ def accept_nonblock
8
+ sock = @svr.accept_nonblock
9
+
10
+ begin
11
+ ssl = OpenSSL::SSL::SSLSocket.new(sock, @ctx)
12
+ ssl.sync_close = true
13
+ ssl.accept if @start_immediately
14
+ ssl
15
+ rescue SSLError => ex
16
+ sock.close
17
+ raise ex
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,74 @@
1
+ module Puma
2
+ module App
3
+ class Status
4
+ def initialize(cli)
5
+ @cli = cli
6
+ @auth_token = nil
7
+ end
8
+ OK_STATUS = '{ "status": "ok" }'.freeze
9
+
10
+ attr_accessor :auth_token
11
+
12
+ def authenticate(env)
13
+ return true unless @auth_token
14
+ env['QUERY_STRING'].to_s.split(/&;/).include?("token=#{@auth_token}")
15
+ end
16
+
17
+ def rack_response(status, body, content_type='application/json')
18
+ headers = {
19
+ 'Content-Type' => content_type,
20
+ 'Content-Length' => body.bytesize.to_s
21
+ }
22
+
23
+ [status, headers, [body]]
24
+ end
25
+
26
+ def call(env)
27
+ unless authenticate(env)
28
+ return rack_response(403, 'Invalid auth token', 'text/plain')
29
+ end
30
+
31
+ case env['PATH_INFO']
32
+ when /\/stop$/
33
+ @cli.stop
34
+ return rack_response(200, OK_STATUS)
35
+
36
+ when /\/halt$/
37
+ @cli.halt
38
+ return rack_response(200, OK_STATUS)
39
+
40
+ when /\/restart$/
41
+ @cli.restart
42
+ return rack_response(200, OK_STATUS)
43
+
44
+ when /\/phased-restart$/
45
+ if !@cli.phased_restart
46
+ return rack_response(404, '{ "error": "phased restart not available" }')
47
+ else
48
+ return rack_response(200, OK_STATUS)
49
+ end
50
+
51
+ when /\/reload-worker-directory$/
52
+ if !@cli.send(:reload_worker_directory)
53
+ return rack_response(404, '{ "error": "reload_worker_directory not available" }')
54
+ else
55
+ return rack_response(200, OK_STATUS)
56
+ end
57
+
58
+ when /\/gc$/
59
+ GC.start
60
+ return rack_response(200, OK_STATUS)
61
+
62
+ when /\/gc-stats$/
63
+ json = "{" + GC.stat.map { |k, v| "\"#{k}\": #{v}" }.join(",") + "}"
64
+ return rack_response(200, json)
65
+
66
+ when /\/stats$/
67
+ return rack_response(200, @cli.stats)
68
+ else
69
+ rack_response 404, "Unsupported action", 'text/plain'
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,413 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'uri'
4
+ require 'socket'
5
+
6
+ require 'puma/const'
7
+ require 'puma/util'
8
+
9
+ module Puma
10
+ class Binder
11
+ include Puma::Const
12
+
13
+ RACK_VERSION = [1,3].freeze
14
+
15
+ def initialize(events)
16
+ @events = events
17
+ @listeners = []
18
+ @inherited_fds = {}
19
+ @activated_sockets = {}
20
+ @unix_paths = []
21
+
22
+ @proto_env = {
23
+ "rack.version".freeze => RACK_VERSION,
24
+ "rack.errors".freeze => events.stderr,
25
+ "rack.multithread".freeze => true,
26
+ "rack.multiprocess".freeze => false,
27
+ "rack.run_once".freeze => false,
28
+ "SCRIPT_NAME".freeze => ENV['SCRIPT_NAME'] || "",
29
+
30
+ # I'd like to set a default CONTENT_TYPE here but some things
31
+ # depend on their not being a default set and inferring
32
+ # it from the content. And so if i set it here, it won't
33
+ # infer properly.
34
+
35
+ "QUERY_STRING".freeze => "",
36
+ SERVER_PROTOCOL => HTTP_11,
37
+ SERVER_SOFTWARE => PUMA_SERVER_STRING,
38
+ GATEWAY_INTERFACE => CGI_VER
39
+ }
40
+
41
+ @envs = {}
42
+ @ios = []
43
+ end
44
+
45
+ attr_reader :listeners, :ios
46
+
47
+ def env(sock)
48
+ @envs.fetch(sock, @proto_env)
49
+ end
50
+
51
+ def close
52
+ @ios.each { |i| i.close }
53
+ @unix_paths.each { |i| File.unlink i }
54
+ end
55
+
56
+ def import_from_env
57
+ remove = []
58
+
59
+ ENV.each do |k,v|
60
+ if k =~ /PUMA_INHERIT_\d+/
61
+ fd, url = v.split(":", 2)
62
+ @inherited_fds[url] = fd.to_i
63
+ remove << k
64
+ elsif k == 'LISTEN_FDS' && ENV['LISTEN_PID'].to_i == $$
65
+ v.to_i.times do |num|
66
+ fd = num + 3
67
+ sock = TCPServer.for_fd(fd)
68
+ begin
69
+ key = [ :unix, Socket.unpack_sockaddr_un(sock.getsockname) ]
70
+ rescue ArgumentError
71
+ port, addr = Socket.unpack_sockaddr_in(sock.getsockname)
72
+ if addr =~ /\:/
73
+ addr = "[#{addr}]"
74
+ end
75
+ key = [ :tcp, addr, port ]
76
+ end
77
+ @activated_sockets[key] = sock
78
+ @events.debug "Registered #{key.join ':'} for activation from LISTEN_FDS"
79
+ end
80
+ remove << k << 'LISTEN_PID'
81
+ end
82
+ end
83
+
84
+ remove.each do |k|
85
+ ENV.delete k
86
+ end
87
+ end
88
+
89
+ def parse(binds, logger)
90
+ binds.each do |str|
91
+ uri = URI.parse str
92
+ case uri.scheme
93
+ when "tcp"
94
+ if fd = @inherited_fds.delete(str)
95
+ io = inherit_tcp_listener uri.host, uri.port, fd
96
+ logger.log "* Inherited #{str}"
97
+ elsif sock = @activated_sockets.delete([ :tcp, uri.host, uri.port ])
98
+ io = inherit_tcp_listener uri.host, uri.port, sock
99
+ logger.log "* Activated #{str}"
100
+ else
101
+ params = Util.parse_query uri.query
102
+
103
+ opt = params.key?('low_latency')
104
+ bak = params.fetch('backlog', 1024).to_i
105
+
106
+ io = add_tcp_listener uri.host, uri.port, opt, bak
107
+ logger.log "* Listening on #{str}"
108
+ end
109
+
110
+ @listeners << [str, io] if io
111
+ when "unix"
112
+ path = "#{uri.host}#{uri.path}".gsub("%20", " ")
113
+
114
+ if fd = @inherited_fds.delete(str)
115
+ io = inherit_unix_listener path, fd
116
+ logger.log "* Inherited #{str}"
117
+ elsif sock = @activated_sockets.delete([ :unix, path ])
118
+ io = inherit_unix_listener path, sock
119
+ logger.log "* Activated #{str}"
120
+ else
121
+ umask = nil
122
+ mode = nil
123
+ backlog = 1024
124
+
125
+ if uri.query
126
+ params = Util.parse_query uri.query
127
+ if u = params['umask']
128
+ # Use Integer() to respect the 0 prefix as octal
129
+ umask = Integer(u)
130
+ end
131
+
132
+ if u = params['mode']
133
+ mode = Integer('0'+u)
134
+ end
135
+
136
+ if u = params['backlog']
137
+ backlog = Integer(u)
138
+ end
139
+ end
140
+
141
+ io = add_unix_listener path, umask, mode, backlog
142
+ logger.log "* Listening on #{str}"
143
+ end
144
+
145
+ @listeners << [str, io]
146
+ when "ssl"
147
+ params = Util.parse_query uri.query
148
+ require 'puma/minissl'
149
+
150
+ MiniSSL.check
151
+
152
+ ctx = MiniSSL::Context.new
153
+
154
+ if defined?(JRUBY_VERSION)
155
+ unless params['keystore']
156
+ @events.error "Please specify the Java keystore via 'keystore='"
157
+ end
158
+
159
+ ctx.keystore = params['keystore']
160
+
161
+ unless params['keystore-pass']
162
+ @events.error "Please specify the Java keystore password via 'keystore-pass='"
163
+ end
164
+
165
+ ctx.keystore_pass = params['keystore-pass']
166
+ ctx.ssl_cipher_list = params['ssl_cipher_list'] if params['ssl_cipher_list']
167
+ else
168
+ unless params['key']
169
+ @events.error "Please specify the SSL key via 'key='"
170
+ end
171
+
172
+ ctx.key = params['key']
173
+
174
+ unless params['cert']
175
+ @events.error "Please specify the SSL cert via 'cert='"
176
+ end
177
+
178
+ ctx.cert = params['cert']
179
+
180
+ if ['peer', 'force_peer'].include?(params['verify_mode'])
181
+ unless params['ca']
182
+ @events.error "Please specify the SSL ca via 'ca='"
183
+ end
184
+ end
185
+
186
+ ctx.ca = params['ca'] if params['ca']
187
+ ctx.ssl_cipher_filter = params['ssl_cipher_filter'] if params['ssl_cipher_filter']
188
+ end
189
+
190
+ if params['verify_mode']
191
+ ctx.verify_mode = case params['verify_mode']
192
+ when "peer"
193
+ MiniSSL::VERIFY_PEER
194
+ when "force_peer"
195
+ MiniSSL::VERIFY_PEER | MiniSSL::VERIFY_FAIL_IF_NO_PEER_CERT
196
+ when "none"
197
+ MiniSSL::VERIFY_NONE
198
+ else
199
+ @events.error "Please specify a valid verify_mode="
200
+ MiniSSL::VERIFY_NONE
201
+ end
202
+ end
203
+
204
+ if params['verification_flags']
205
+ ctx.verification_flags = Array(params['verification_flags']).
206
+ map { |flag| MiniSSL::VERIFICATION_FLAGS.fetch(flag) }.
207
+ inject { |sum, flag| sum ? sum | flag : flag }
208
+ end
209
+
210
+ if fd = @inherited_fds.delete(str)
211
+ logger.log "* Inherited #{str}"
212
+ io = inherit_ssl_listener fd, ctx
213
+ elsif sock = @activated_sockets.delete([ :tcp, uri.host, uri.port ])
214
+ io = inherit_ssl_listener sock, ctx
215
+ logger.log "* Activated #{str}"
216
+ else
217
+ io = add_ssl_listener uri.host, uri.port, ctx
218
+ logger.log "* Listening on #{str}"
219
+ end
220
+
221
+ @listeners << [str, io] if io
222
+ else
223
+ logger.error "Invalid URI: #{str}"
224
+ end
225
+ end
226
+
227
+ # If we inherited fds but didn't use them (because of a
228
+ # configuration change), then be sure to close them.
229
+ @inherited_fds.each do |str, fd|
230
+ logger.log "* Closing unused inherited connection: #{str}"
231
+
232
+ begin
233
+ IO.for_fd(fd).close
234
+ rescue SystemCallError
235
+ end
236
+
237
+ # We have to unlink a unix socket path that's not being used
238
+ uri = URI.parse str
239
+ if uri.scheme == "unix"
240
+ path = "#{uri.host}#{uri.path}"
241
+ File.unlink path
242
+ end
243
+ end
244
+
245
+ # Also close any unused activated sockets
246
+ @activated_sockets.each do |key, sock|
247
+ logger.log "* Closing unused activated socket: #{key.join ':'}"
248
+ begin
249
+ sock.close
250
+ rescue SystemCallError
251
+ end
252
+ # We have to unlink a unix socket path that's not being used
253
+ File.unlink key[1] if key[0] == :unix
254
+ end
255
+ end
256
+
257
+ def loopback_addresses
258
+ Socket.ip_address_list.select do |addrinfo|
259
+ addrinfo.ipv6_loopback? || addrinfo.ipv4_loopback?
260
+ end.map { |addrinfo| addrinfo.ip_address }.uniq
261
+ end
262
+
263
+ # Tell the server to listen on host +host+, port +port+.
264
+ # If +optimize_for_latency+ is true (the default) then clients connecting
265
+ # will be optimized for latency over throughput.
266
+ #
267
+ # +backlog+ indicates how many unaccepted connections the kernel should
268
+ # allow to accumulate before returning connection refused.
269
+ #
270
+ def add_tcp_listener(host, port, optimize_for_latency=true, backlog=1024)
271
+ if host == "localhost"
272
+ loopback_addresses.each do |addr|
273
+ add_tcp_listener addr, port, optimize_for_latency, backlog
274
+ end
275
+ return
276
+ end
277
+
278
+ host = host[1..-2] if host and host[0..0] == '['
279
+ s = TCPServer.new(host, port)
280
+ if optimize_for_latency
281
+ s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
282
+ end
283
+ s.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
284
+ s.listen backlog
285
+ @connected_port = s.addr[1]
286
+
287
+ @ios << s
288
+ s
289
+ end
290
+
291
+ attr_reader :connected_port
292
+
293
+ def inherit_tcp_listener(host, port, fd)
294
+ if fd.kind_of? TCPServer
295
+ s = fd
296
+ else
297
+ s = TCPServer.for_fd(fd)
298
+ end
299
+
300
+ @ios << s
301
+ s
302
+ end
303
+
304
+ def add_ssl_listener(host, port, ctx,
305
+ optimize_for_latency=true, backlog=1024)
306
+ require 'puma/minissl'
307
+
308
+ MiniSSL.check
309
+
310
+ if host == "localhost"
311
+ loopback_addresses.each do |addr|
312
+ add_ssl_listener addr, port, ctx, optimize_for_latency, backlog
313
+ end
314
+ return
315
+ end
316
+
317
+ host = host[1..-2] if host[0..0] == '['
318
+ s = TCPServer.new(host, port)
319
+ if optimize_for_latency
320
+ s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
321
+ end
322
+ s.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
323
+ s.listen backlog
324
+
325
+
326
+ ssl = MiniSSL::Server.new s, ctx
327
+ env = @proto_env.dup
328
+ env[HTTPS_KEY] = HTTPS
329
+ @envs[ssl] = env
330
+
331
+ @ios << ssl
332
+ s
333
+ end
334
+
335
+ def inherit_ssl_listener(fd, ctx)
336
+ require 'puma/minissl'
337
+ MiniSSL.check
338
+
339
+ if fd.kind_of? TCPServer
340
+ s = fd
341
+ else
342
+ s = TCPServer.for_fd(fd)
343
+ end
344
+ ssl = MiniSSL::Server.new(s, ctx)
345
+
346
+ env = @proto_env.dup
347
+ env[HTTPS_KEY] = HTTPS
348
+ @envs[ssl] = env
349
+
350
+ @ios << ssl
351
+
352
+ s
353
+ end
354
+
355
+ # Tell the server to listen on +path+ as a UNIX domain socket.
356
+ #
357
+ def add_unix_listener(path, umask=nil, mode=nil, backlog=1024)
358
+ @unix_paths << path
359
+
360
+ # Let anyone connect by default
361
+ umask ||= 0
362
+
363
+ begin
364
+ old_mask = File.umask(umask)
365
+
366
+ if File.exist? path
367
+ begin
368
+ old = UNIXSocket.new path
369
+ rescue SystemCallError, IOError
370
+ File.unlink path
371
+ else
372
+ old.close
373
+ raise "There is already a server bound to: #{path}"
374
+ end
375
+ end
376
+
377
+ s = UNIXServer.new(path)
378
+ s.listen backlog
379
+ @ios << s
380
+ ensure
381
+ File.umask old_mask
382
+ end
383
+
384
+ if mode
385
+ File.chmod mode, path
386
+ end
387
+
388
+ env = @proto_env.dup
389
+ env[REMOTE_ADDR] = "127.0.0.1"
390
+ @envs[s] = env
391
+
392
+ s
393
+ end
394
+
395
+ def inherit_unix_listener(path, fd)
396
+ @unix_paths << path
397
+
398
+ if fd.kind_of? TCPServer
399
+ s = fd
400
+ else
401
+ s = UNIXServer.for_fd fd
402
+ end
403
+ @ios << s
404
+
405
+ env = @proto_env.dup
406
+ env[REMOTE_ADDR] = "127.0.0.1"
407
+ @envs[s] = env
408
+
409
+ s
410
+ end
411
+
412
+ end
413
+ end