puma-simon 3.7.1
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.
- checksums.yaml +7 -0
- data/.github/issue_template.md +20 -0
- data/.gitignore +18 -0
- data/.hoeignore +12 -0
- data/.travis.yml +29 -0
- data/DEPLOYMENT.md +91 -0
- data/Gemfile +12 -0
- data/History.md +1254 -0
- data/LICENSE +26 -0
- data/Manifest.txt +78 -0
- data/README.md +353 -0
- data/Rakefile +158 -0
- data/Release.md +9 -0
- data/bin/puma +10 -0
- data/bin/puma-wild +31 -0
- data/bin/pumactl +12 -0
- data/docs/nginx.md +80 -0
- data/docs/signals.md +43 -0
- data/docs/systemd.md +197 -0
- data/examples/CA/cacert.pem +23 -0
- data/examples/CA/newcerts/cert_1.pem +19 -0
- data/examples/CA/newcerts/cert_2.pem +19 -0
- data/examples/CA/private/cakeypair.pem +30 -0
- data/examples/CA/serial +1 -0
- data/examples/config.rb +200 -0
- data/examples/plugins/redis_stop_puma.rb +46 -0
- data/examples/puma/cert_puma.pem +19 -0
- data/examples/puma/client-certs/ca.crt +19 -0
- data/examples/puma/client-certs/ca.key +27 -0
- data/examples/puma/client-certs/client.crt +19 -0
- data/examples/puma/client-certs/client.key +27 -0
- data/examples/puma/client-certs/client_expired.crt +19 -0
- data/examples/puma/client-certs/client_expired.key +27 -0
- data/examples/puma/client-certs/client_unknown.crt +19 -0
- data/examples/puma/client-certs/client_unknown.key +27 -0
- data/examples/puma/client-certs/generate.rb +78 -0
- data/examples/puma/client-certs/keystore.jks +0 -0
- data/examples/puma/client-certs/server.crt +19 -0
- data/examples/puma/client-certs/server.key +27 -0
- data/examples/puma/client-certs/server.p12 +0 -0
- data/examples/puma/client-certs/unknown_ca.crt +19 -0
- data/examples/puma/client-certs/unknown_ca.key +27 -0
- data/examples/puma/csr_puma.pem +11 -0
- data/examples/puma/keystore.jks +0 -0
- data/examples/puma/puma_keypair.pem +15 -0
- data/examples/qc_config.rb +13 -0
- data/ext/puma_http11/PumaHttp11Service.java +17 -0
- data/ext/puma_http11/ext_help.h +15 -0
- data/ext/puma_http11/extconf.rb +15 -0
- data/ext/puma_http11/http11_parser.c +1069 -0
- data/ext/puma_http11/http11_parser.h +65 -0
- data/ext/puma_http11/http11_parser.java.rl +161 -0
- data/ext/puma_http11/http11_parser.rl +147 -0
- data/ext/puma_http11/http11_parser_common.rl +54 -0
- data/ext/puma_http11/io_buffer.c +155 -0
- data/ext/puma_http11/mini_ssl.c +457 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +234 -0
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +473 -0
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +339 -0
- data/ext/puma_http11/puma_http11.c +500 -0
- data/gemfiles/2.1-Gemfile +12 -0
- data/lib/puma.rb +15 -0
- data/lib/puma/accept_nonblock.rb +23 -0
- data/lib/puma/app/status.rb +66 -0
- data/lib/puma/binder.rb +402 -0
- data/lib/puma/cli.rb +220 -0
- data/lib/puma/client.rb +434 -0
- data/lib/puma/cluster.rb +510 -0
- data/lib/puma/commonlogger.rb +106 -0
- data/lib/puma/compat.rb +14 -0
- data/lib/puma/configuration.rb +364 -0
- data/lib/puma/const.rb +224 -0
- data/lib/puma/control_cli.rb +259 -0
- data/lib/puma/convenient.rb +23 -0
- data/lib/puma/daemon_ext.rb +31 -0
- data/lib/puma/delegation.rb +11 -0
- data/lib/puma/detect.rb +13 -0
- data/lib/puma/dsl.rb +486 -0
- data/lib/puma/events.rb +152 -0
- data/lib/puma/io_buffer.rb +7 -0
- data/lib/puma/java_io_buffer.rb +45 -0
- data/lib/puma/jruby_restart.rb +83 -0
- data/lib/puma/launcher.rb +410 -0
- data/lib/puma/minissl.rb +221 -0
- data/lib/puma/null_io.rb +42 -0
- data/lib/puma/plugin.rb +115 -0
- data/lib/puma/plugin/tmp_restart.rb +35 -0
- data/lib/puma/rack/backports/uri/common_193.rb +33 -0
- data/lib/puma/rack/builder.rb +298 -0
- data/lib/puma/rack/urlmap.rb +91 -0
- data/lib/puma/rack_default.rb +7 -0
- data/lib/puma/reactor.rb +210 -0
- data/lib/puma/runner.rb +171 -0
- data/lib/puma/server.rb +949 -0
- data/lib/puma/single.rb +112 -0
- data/lib/puma/state_file.rb +29 -0
- data/lib/puma/tcp_logger.rb +39 -0
- data/lib/puma/thread_pool.rb +297 -0
- data/lib/puma/util.rb +128 -0
- data/lib/rack/handler/puma.rb +78 -0
- data/puma.gemspec +52 -0
- data/test/ab_rs.rb +22 -0
- data/test/config.rb +2 -0
- data/test/config/app.rb +9 -0
- data/test/config/plugin.rb +1 -0
- data/test/config/settings.rb +2 -0
- data/test/config/state_file_testing_config.rb +14 -0
- data/test/hello-bind.ru +2 -0
- data/test/hello-delay.ru +3 -0
- data/test/hello-map.ru +3 -0
- data/test/hello-post.ru +4 -0
- data/test/hello-stuck.ru +1 -0
- data/test/hello-tcp.ru +5 -0
- data/test/hello.ru +1 -0
- data/test/hijack.ru +6 -0
- data/test/hijack2.ru +5 -0
- data/test/lobster.ru +4 -0
- data/test/shell/run.sh +24 -0
- data/test/shell/t1.rb +19 -0
- data/test/shell/t1_conf.rb +3 -0
- data/test/shell/t2.rb +17 -0
- data/test/shell/t2_conf.rb +6 -0
- data/test/shell/t3.rb +25 -0
- data/test/shell/t3_conf.rb +5 -0
- data/test/slow.ru +4 -0
- data/test/ssl_config.rb +4 -0
- data/test/test_app_status.rb +93 -0
- data/test/test_binder.rb +31 -0
- data/test/test_cli.rb +209 -0
- data/test/test_config.rb +95 -0
- data/test/test_events.rb +161 -0
- data/test/test_helper.rb +50 -0
- data/test/test_http10.rb +27 -0
- data/test/test_http11.rb +186 -0
- data/test/test_integration.rb +247 -0
- data/test/test_iobuffer.rb +39 -0
- data/test/test_minissl.rb +29 -0
- data/test/test_null_io.rb +49 -0
- data/test/test_persistent.rb +245 -0
- data/test/test_puma_server.rb +626 -0
- data/test/test_puma_server_ssl.rb +222 -0
- data/test/test_rack_handler.rb +57 -0
- data/test/test_rack_server.rb +138 -0
- data/test/test_tcp_logger.rb +39 -0
- data/test/test_tcp_rack.rb +36 -0
- data/test/test_thread_pool.rb +250 -0
- data/test/test_unix_socket.rb +35 -0
- data/test/test_web_server.rb +88 -0
- data/tools/jungle/README.md +9 -0
- data/tools/jungle/init.d/README.md +59 -0
- data/tools/jungle/init.d/puma +421 -0
- data/tools/jungle/init.d/run-puma +18 -0
- data/tools/jungle/upstart/README.md +61 -0
- data/tools/jungle/upstart/puma-manager.conf +31 -0
- data/tools/jungle/upstart/puma.conf +69 -0
- data/tools/trickletest.rb +45 -0
- metadata +297 -0
data/lib/puma.rb
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
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
|
+
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,66 @@
|
|
|
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 /\/stats$/
|
|
59
|
+
return rack_response(200, @cli.stats)
|
|
60
|
+
else
|
|
61
|
+
rack_response 404, "Unsupported action", 'text/plain'
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
data/lib/puma/binder.rb
ADDED
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
require 'uri'
|
|
2
|
+
require 'socket'
|
|
3
|
+
|
|
4
|
+
require 'puma/const'
|
|
5
|
+
require 'puma/util'
|
|
6
|
+
|
|
7
|
+
module Puma
|
|
8
|
+
class Binder
|
|
9
|
+
include Puma::Const
|
|
10
|
+
|
|
11
|
+
RACK_VERSION = [1,3].freeze
|
|
12
|
+
|
|
13
|
+
def initialize(events)
|
|
14
|
+
@events = events
|
|
15
|
+
@listeners = []
|
|
16
|
+
@inherited_fds = {}
|
|
17
|
+
@activated_sockets = {}
|
|
18
|
+
@unix_paths = []
|
|
19
|
+
|
|
20
|
+
@proto_env = {
|
|
21
|
+
"rack.version".freeze => RACK_VERSION,
|
|
22
|
+
"rack.errors".freeze => events.stderr,
|
|
23
|
+
"rack.multithread".freeze => true,
|
|
24
|
+
"rack.multiprocess".freeze => false,
|
|
25
|
+
"rack.run_once".freeze => false,
|
|
26
|
+
"SCRIPT_NAME".freeze => ENV['SCRIPT_NAME'] || "",
|
|
27
|
+
|
|
28
|
+
# I'd like to set a default CONTENT_TYPE here but some things
|
|
29
|
+
# depend on their not being a default set and inferring
|
|
30
|
+
# it from the content. And so if i set it here, it won't
|
|
31
|
+
# infer properly.
|
|
32
|
+
|
|
33
|
+
"QUERY_STRING".freeze => "",
|
|
34
|
+
SERVER_PROTOCOL => HTTP_11,
|
|
35
|
+
SERVER_SOFTWARE => PUMA_SERVER_STRING,
|
|
36
|
+
GATEWAY_INTERFACE => CGI_VER
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@envs = {}
|
|
40
|
+
@ios = []
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
attr_reader :listeners, :ios
|
|
44
|
+
|
|
45
|
+
def env(sock)
|
|
46
|
+
@envs.fetch(sock, @proto_env)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def close
|
|
50
|
+
@ios.each { |i| i.close }
|
|
51
|
+
@unix_paths.each { |i| File.unlink i }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def import_from_env
|
|
55
|
+
remove = []
|
|
56
|
+
|
|
57
|
+
ENV.each do |k,v|
|
|
58
|
+
if k =~ /PUMA_INHERIT_\d+/
|
|
59
|
+
fd, url = v.split(":", 2)
|
|
60
|
+
@inherited_fds[url] = fd.to_i
|
|
61
|
+
remove << k
|
|
62
|
+
elsif k == 'LISTEN_FDS' && ENV['LISTEN_PID'].to_i == $$
|
|
63
|
+
v.to_i.times do |num|
|
|
64
|
+
fd = num + 3
|
|
65
|
+
sock = TCPServer.for_fd(fd)
|
|
66
|
+
begin
|
|
67
|
+
key = [ :unix, Socket.unpack_sockaddr_un(sock.getsockname) ]
|
|
68
|
+
rescue ArgumentError
|
|
69
|
+
port, addr = Socket.unpack_sockaddr_in(sock.getsockname)
|
|
70
|
+
if addr =~ /\:/
|
|
71
|
+
addr = "[#{addr}]"
|
|
72
|
+
end
|
|
73
|
+
key = [ :tcp, addr, port ]
|
|
74
|
+
end
|
|
75
|
+
@activated_sockets[key] = sock
|
|
76
|
+
@events.debug "Registered #{key.join ':'} for activation from LISTEN_FDS"
|
|
77
|
+
end
|
|
78
|
+
remove << k << 'LISTEN_PID'
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
remove.each do |k|
|
|
83
|
+
ENV.delete k
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def parse(binds, logger)
|
|
88
|
+
binds.each do |str|
|
|
89
|
+
uri = URI.parse str
|
|
90
|
+
case uri.scheme
|
|
91
|
+
when "tcp"
|
|
92
|
+
if fd = @inherited_fds.delete(str)
|
|
93
|
+
logger.log "* Inherited #{str}"
|
|
94
|
+
io = inherit_tcp_listener uri.host, uri.port, fd
|
|
95
|
+
elsif sock = @activated_sockets.delete([ :tcp, uri.host, uri.port ])
|
|
96
|
+
logger.log "* Activated #{str}"
|
|
97
|
+
io = inherit_tcp_listener uri.host, uri.port, sock
|
|
98
|
+
else
|
|
99
|
+
params = Util.parse_query uri.query
|
|
100
|
+
|
|
101
|
+
opt = params.key?('low_latency')
|
|
102
|
+
bak = params.fetch('backlog', 1024).to_i
|
|
103
|
+
|
|
104
|
+
logger.log "* Listening on #{str}"
|
|
105
|
+
io = add_tcp_listener uri.host, uri.port, opt, bak
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
@listeners << [str, io] if io
|
|
109
|
+
when "unix"
|
|
110
|
+
path = "#{uri.host}#{uri.path}".gsub("%20", " ")
|
|
111
|
+
|
|
112
|
+
if fd = @inherited_fds.delete(str)
|
|
113
|
+
logger.log "* Inherited #{str}"
|
|
114
|
+
io = inherit_unix_listener path, fd
|
|
115
|
+
elsif sock = @activated_sockets.delete([ :unix, path ])
|
|
116
|
+
logger.log "* Activated #{str}"
|
|
117
|
+
io = inherit_unix_listener path, sock
|
|
118
|
+
else
|
|
119
|
+
logger.log "* Listening on #{str}"
|
|
120
|
+
|
|
121
|
+
umask = nil
|
|
122
|
+
mode = nil
|
|
123
|
+
backlog = nil
|
|
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
|
+
end
|
|
143
|
+
|
|
144
|
+
@listeners << [str, io]
|
|
145
|
+
when "ssl"
|
|
146
|
+
params = Util.parse_query uri.query
|
|
147
|
+
require 'puma/minissl'
|
|
148
|
+
|
|
149
|
+
MiniSSL.check
|
|
150
|
+
|
|
151
|
+
ctx = MiniSSL::Context.new
|
|
152
|
+
|
|
153
|
+
if defined?(JRUBY_VERSION)
|
|
154
|
+
unless params['keystore']
|
|
155
|
+
@events.error "Please specify the Java keystore via 'keystore='"
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
ctx.keystore = params['keystore']
|
|
159
|
+
|
|
160
|
+
unless params['keystore-pass']
|
|
161
|
+
@events.error "Please specify the Java keystore password via 'keystore-pass='"
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
ctx.keystore_pass = params['keystore-pass']
|
|
165
|
+
else
|
|
166
|
+
unless params['key']
|
|
167
|
+
@events.error "Please specify the SSL key via 'key='"
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
ctx.key = params['key']
|
|
171
|
+
|
|
172
|
+
unless params['cert']
|
|
173
|
+
@events.error "Please specify the SSL cert via 'cert='"
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
ctx.cert = params['cert']
|
|
177
|
+
|
|
178
|
+
if ['peer', 'force_peer'].include?(params['verify_mode'])
|
|
179
|
+
unless params['ca']
|
|
180
|
+
@events.error "Please specify the SSL ca via 'ca='"
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
ctx.ca = params['ca'] if params['ca']
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
if params['verify_mode']
|
|
188
|
+
ctx.verify_mode = case params['verify_mode']
|
|
189
|
+
when "peer"
|
|
190
|
+
MiniSSL::VERIFY_PEER
|
|
191
|
+
when "force_peer"
|
|
192
|
+
MiniSSL::VERIFY_PEER | MiniSSL::VERIFY_FAIL_IF_NO_PEER_CERT
|
|
193
|
+
when "none"
|
|
194
|
+
MiniSSL::VERIFY_NONE
|
|
195
|
+
else
|
|
196
|
+
@events.error "Please specify a valid verify_mode="
|
|
197
|
+
MiniSSL::VERIFY_NONE
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
if fd = @inherited_fds.delete(str)
|
|
202
|
+
logger.log "* Inherited #{str}"
|
|
203
|
+
io = inherit_ssl_listener fd, ctx
|
|
204
|
+
elsif sock = @activated_sockets.delete([ :tcp, uri.host, uri.port ])
|
|
205
|
+
logger.log "* Activated #{str}"
|
|
206
|
+
io = inherit_ssl_listener sock, ctx
|
|
207
|
+
else
|
|
208
|
+
logger.log "* Listening on #{str}"
|
|
209
|
+
io = add_ssl_listener uri.host, uri.port, ctx
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
@listeners << [str, io] if io
|
|
213
|
+
else
|
|
214
|
+
logger.error "Invalid URI: #{str}"
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
# If we inherited fds but didn't use them (because of a
|
|
219
|
+
# configuration change), then be sure to close them.
|
|
220
|
+
@inherited_fds.each do |str, fd|
|
|
221
|
+
logger.log "* Closing unused inherited connection: #{str}"
|
|
222
|
+
|
|
223
|
+
begin
|
|
224
|
+
IO.for_fd(fd).close
|
|
225
|
+
rescue SystemCallError
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# We have to unlink a unix socket path that's not being used
|
|
229
|
+
uri = URI.parse str
|
|
230
|
+
if uri.scheme == "unix"
|
|
231
|
+
path = "#{uri.host}#{uri.path}"
|
|
232
|
+
File.unlink path
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# Also close any unused activated sockets
|
|
237
|
+
@activated_sockets.each do |key, sock|
|
|
238
|
+
logger.log "* Closing unused activated socket: #{key.join ':'}"
|
|
239
|
+
begin
|
|
240
|
+
sock.close
|
|
241
|
+
rescue SystemCallError
|
|
242
|
+
end
|
|
243
|
+
# We have to unlink a unix socket path that's not being used
|
|
244
|
+
File.unlink key[1] if key[0] == :unix
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def localhost_addresses
|
|
249
|
+
addrs = TCPSocket.gethostbyname "localhost"
|
|
250
|
+
addrs[3..-1].uniq
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# Tell the server to listen on host +host+, port +port+.
|
|
254
|
+
# If +optimize_for_latency+ is true (the default) then clients connecting
|
|
255
|
+
# will be optimized for latency over throughput.
|
|
256
|
+
#
|
|
257
|
+
# +backlog+ indicates how many unaccepted connections the kernel should
|
|
258
|
+
# allow to accumulate before returning connection refused.
|
|
259
|
+
#
|
|
260
|
+
def add_tcp_listener(host, port, optimize_for_latency=true, backlog=1024)
|
|
261
|
+
if host == "localhost"
|
|
262
|
+
localhost_addresses.each do |addr|
|
|
263
|
+
add_tcp_listener addr, port, optimize_for_latency, backlog
|
|
264
|
+
end
|
|
265
|
+
return
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
host = host[1..-2] if host and host[0..0] == '['
|
|
269
|
+
s = TCPServer.new(host, port)
|
|
270
|
+
if optimize_for_latency
|
|
271
|
+
s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
|
272
|
+
end
|
|
273
|
+
s.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
|
|
274
|
+
s.listen backlog
|
|
275
|
+
@connected_port = s.addr[1]
|
|
276
|
+
|
|
277
|
+
@ios << s
|
|
278
|
+
s
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
attr_reader :connected_port
|
|
282
|
+
|
|
283
|
+
def inherit_tcp_listener(host, port, fd)
|
|
284
|
+
if fd.kind_of? TCPServer
|
|
285
|
+
s = fd
|
|
286
|
+
else
|
|
287
|
+
s = TCPServer.for_fd(fd)
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
@ios << s
|
|
291
|
+
s
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
def add_ssl_listener(host, port, ctx,
|
|
295
|
+
optimize_for_latency=true, backlog=1024)
|
|
296
|
+
require 'puma/minissl'
|
|
297
|
+
|
|
298
|
+
MiniSSL.check
|
|
299
|
+
|
|
300
|
+
if host == "localhost"
|
|
301
|
+
localhost_addresses.each do |addr|
|
|
302
|
+
add_ssl_listener addr, port, ctx, optimize_for_latency, backlog
|
|
303
|
+
end
|
|
304
|
+
return
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
host = host[1..-2] if host[0..0] == '['
|
|
308
|
+
s = TCPServer.new(host, port)
|
|
309
|
+
if optimize_for_latency
|
|
310
|
+
s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
|
311
|
+
end
|
|
312
|
+
s.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
|
|
313
|
+
s.listen backlog
|
|
314
|
+
|
|
315
|
+
ssl = MiniSSL::Server.new s, ctx
|
|
316
|
+
env = @proto_env.dup
|
|
317
|
+
env[HTTPS_KEY] = HTTPS
|
|
318
|
+
@envs[ssl] = env
|
|
319
|
+
|
|
320
|
+
@ios << ssl
|
|
321
|
+
s
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
def inherit_ssl_listener(fd, ctx)
|
|
325
|
+
require 'puma/minissl'
|
|
326
|
+
MiniSSL.check
|
|
327
|
+
|
|
328
|
+
if fd.kind_of? TCPServer
|
|
329
|
+
s = fd
|
|
330
|
+
else
|
|
331
|
+
s = TCPServer.for_fd(fd)
|
|
332
|
+
end
|
|
333
|
+
ssl = MiniSSL::Server.new(s, ctx)
|
|
334
|
+
|
|
335
|
+
env = @proto_env.dup
|
|
336
|
+
env[HTTPS_KEY] = HTTPS
|
|
337
|
+
@envs[ssl] = env
|
|
338
|
+
|
|
339
|
+
@ios << ssl
|
|
340
|
+
|
|
341
|
+
s
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
# Tell the server to listen on +path+ as a UNIX domain socket.
|
|
345
|
+
#
|
|
346
|
+
def add_unix_listener(path, umask=nil, mode=nil, backlog=nil)
|
|
347
|
+
@unix_paths << path
|
|
348
|
+
|
|
349
|
+
# Let anyone connect by default
|
|
350
|
+
umask ||= 0
|
|
351
|
+
|
|
352
|
+
begin
|
|
353
|
+
old_mask = File.umask(umask)
|
|
354
|
+
|
|
355
|
+
if File.exist? path
|
|
356
|
+
begin
|
|
357
|
+
old = UNIXSocket.new path
|
|
358
|
+
rescue SystemCallError, IOError
|
|
359
|
+
File.unlink path
|
|
360
|
+
else
|
|
361
|
+
old.close
|
|
362
|
+
raise "There is already a server bound to: #{path}"
|
|
363
|
+
end
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
s = UNIXServer.new(path)
|
|
367
|
+
s.listen backlog if backlog
|
|
368
|
+
@ios << s
|
|
369
|
+
ensure
|
|
370
|
+
File.umask old_mask
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
if mode
|
|
374
|
+
File.chmod mode, path
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
env = @proto_env.dup
|
|
378
|
+
env[REMOTE_ADDR] = "127.0.0.1"
|
|
379
|
+
@envs[s] = env
|
|
380
|
+
|
|
381
|
+
s
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
def inherit_unix_listener(path, fd)
|
|
385
|
+
@unix_paths << path
|
|
386
|
+
|
|
387
|
+
if fd.kind_of? TCPServer
|
|
388
|
+
s = fd
|
|
389
|
+
else
|
|
390
|
+
s = UNIXServer.for_fd fd
|
|
391
|
+
end
|
|
392
|
+
@ios << s
|
|
393
|
+
|
|
394
|
+
env = @proto_env.dup
|
|
395
|
+
env[REMOTE_ADDR] = "127.0.0.1"
|
|
396
|
+
@envs[s] = env
|
|
397
|
+
|
|
398
|
+
s
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
end
|
|
402
|
+
end
|