tipi 0.41 → 0.42
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 +4 -4
- data/.github/workflows/test.yml +4 -0
- data/.gitignore +3 -1
- data/CHANGELOG.md +11 -0
- data/Gemfile +5 -1
- data/Gemfile.lock +26 -12
- data/benchmarks/bm_http1_parser.rb +61 -0
- data/bin/benchmark +37 -0
- data/bin/h1pd +6 -0
- data/bin/tipi +3 -21
- data/df/server.rb +1 -1
- data/df/server_utils.rb +49 -44
- data/examples/full_service.rb +13 -0
- data/examples/http1_parser.rb +10 -8
- data/examples/http_server.rb +4 -1
- data/examples/https_server.rb +3 -0
- data/examples/servername_cb.rb +37 -0
- data/ext/tipi/extconf.rb +3 -2
- data/ext/tipi/http1_parser.c +478 -189
- data/lib/tipi.rb +84 -3
- data/lib/tipi/acme.rb +308 -0
- data/lib/tipi/cli.rb +30 -0
- data/lib/tipi/digital_fabric/agent.rb +2 -2
- data/lib/tipi/digital_fabric/agent_proxy.rb +4 -3
- data/lib/tipi/digital_fabric/executive.rb +6 -2
- data/lib/tipi/digital_fabric/protocol.rb +2 -2
- data/lib/tipi/digital_fabric/request_adapter.rb +0 -4
- data/lib/tipi/digital_fabric/service.rb +5 -10
- data/lib/tipi/http1_adapter.rb +55 -100
- data/lib/tipi/http2_adapter.rb +19 -6
- data/lib/tipi/http2_stream.rb +39 -43
- data/lib/tipi/version.rb +1 -1
- data/security/http1.rb +12 -0
- data/test/helper.rb +60 -11
- data/test/test_http1_parser.rb +586 -0
- data/test/test_http_server.rb +0 -27
- data/test/test_request.rb +1 -28
- data/tipi.gemspec +6 -5
- metadata +48 -27
- data/examples/automatic_certificate.rb +0 -193
- data/lib/tipi/http1_adapter_new.rb +0 -293
data/test/test_http_server.rb
CHANGED
@@ -9,33 +9,6 @@ class String
|
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
-
class IO
|
13
|
-
# Creates two mockup sockets for simulating server-client communication
|
14
|
-
def self.server_client_mockup
|
15
|
-
server_in, client_out = IO.pipe
|
16
|
-
client_in, server_out = IO.pipe
|
17
|
-
|
18
|
-
server_connection = mockup_connection(server_in, server_out, client_out)
|
19
|
-
client_connection = mockup_connection(client_in, client_out, server_out)
|
20
|
-
|
21
|
-
[server_connection, client_connection]
|
22
|
-
end
|
23
|
-
|
24
|
-
def self.mockup_connection(input, output, output2)
|
25
|
-
eg(
|
26
|
-
:read => ->(*args) { input.read(*args) },
|
27
|
-
:read_loop => ->(*args, &block) { input.read_loop(*args, &block) },
|
28
|
-
:recv_loop => ->(*args, &block) { input.read_loop(*args, &block) },
|
29
|
-
:readpartial => ->(*args) { input.readpartial(*args) },
|
30
|
-
:recv => ->(*args) { input.readpartial(*args) },
|
31
|
-
:<< => ->(*args) { output.write(*args) },
|
32
|
-
:write => ->(*args) { output.write(*args) },
|
33
|
-
:close => -> { output.close },
|
34
|
-
:eof? => -> { output2.closed? }
|
35
|
-
)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
12
|
class HTTP1ServerTest < MiniTest::Test
|
40
13
|
def teardown
|
41
14
|
@server&.interrupt if @server&.alive?
|
data/test/test_request.rb
CHANGED
@@ -9,33 +9,6 @@ class String
|
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
-
class IO
|
13
|
-
# Creates two mockup sockets for simulating server-client communication
|
14
|
-
def self.server_client_mockup
|
15
|
-
server_in, client_out = IO.pipe
|
16
|
-
client_in, server_out = IO.pipe
|
17
|
-
|
18
|
-
server_connection = mockup_connection(server_in, server_out, client_out)
|
19
|
-
client_connection = mockup_connection(client_in, client_out, server_out)
|
20
|
-
|
21
|
-
[server_connection, client_connection]
|
22
|
-
end
|
23
|
-
|
24
|
-
def self.mockup_connection(input, output, output2)
|
25
|
-
eg(
|
26
|
-
:read => ->(*args) { input.read(*args) },
|
27
|
-
:read_loop => ->(*args, &block) { input.read_loop(*args, &block) },
|
28
|
-
:recv_loop => ->(*args, &block) { input.read_loop(*args, &block) },
|
29
|
-
:readpartial => ->(*args) { input.readpartial(*args) },
|
30
|
-
:recv => ->(*args) { input.readpartial(*args) },
|
31
|
-
:<< => ->(*args) { output.write(*args) },
|
32
|
-
:write => ->(*args) { output.write(*args) },
|
33
|
-
:close => -> { output.close },
|
34
|
-
:eof? => -> { output2.closed? }
|
35
|
-
)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
12
|
class RequestHeadersTest < MiniTest::Test
|
40
13
|
def teardown
|
41
14
|
@server&.interrupt if @server&.alive?
|
@@ -65,7 +38,7 @@ class RequestHeadersTest < MiniTest::Test
|
|
65
38
|
assert_kind_of Qeweney::Request, req
|
66
39
|
assert_equal 'blah.com', req.headers['host']
|
67
40
|
assert_equal 'bar', req.headers['foo']
|
68
|
-
assert_equal ['1', '
|
41
|
+
assert_equal ['1', '2', '3'], req.headers['hi']
|
69
42
|
assert_equal 'get', req.headers[':method']
|
70
43
|
assert_equal '/titi', req.headers[':path']
|
71
44
|
end
|
data/tipi.gemspec
CHANGED
@@ -20,24 +20,25 @@ Gem::Specification.new do |s|
|
|
20
20
|
|
21
21
|
s.executables = ['tipi']
|
22
22
|
|
23
|
-
s.add_runtime_dependency 'polyphony', '~>0.
|
24
|
-
s.add_runtime_dependency 'qeweney', '~>0.
|
23
|
+
s.add_runtime_dependency 'polyphony', '~>0.69'
|
24
|
+
s.add_runtime_dependency 'qeweney', '~>0.14'
|
25
|
+
s.add_runtime_dependency 'extralite', '~>1.2'
|
25
26
|
|
26
|
-
s.add_runtime_dependency '
|
27
|
-
s.add_runtime_dependency 'http-2', '~>0.10.0'
|
27
|
+
s.add_runtime_dependency 'http-2', '~>0.11'
|
28
28
|
s.add_runtime_dependency 'rack', '>=2.0.8', '<2.3.0'
|
29
29
|
s.add_runtime_dependency 'websocket', '~>1.2.8'
|
30
30
|
s.add_runtime_dependency 'acme-client', '~>2.0.8'
|
31
|
+
s.add_runtime_dependency 'localhost', '~>1.1.4'
|
31
32
|
|
32
33
|
# for digital fabric
|
33
34
|
s.add_runtime_dependency 'msgpack', '~>1.4.2'
|
34
35
|
|
35
36
|
s.add_development_dependency 'rake-compiler', '1.1.1'
|
36
37
|
s.add_development_dependency 'rake', '~>12.3.3'
|
37
|
-
s.add_development_dependency 'localhost', '~>1.1.4'
|
38
38
|
s.add_development_dependency 'minitest', '~>5.11.3'
|
39
39
|
s.add_development_dependency 'minitest-reporters', '~>1.4.2'
|
40
40
|
s.add_development_dependency 'simplecov', '~>0.17.1'
|
41
41
|
|
42
42
|
s.add_development_dependency 'cuba', '~>3.9.3'
|
43
|
+
s.add_development_dependency 'http_parser.rb', '0.7.0'
|
43
44
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tipi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.42'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sharon Rosner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-08-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: polyphony
|
@@ -16,56 +16,56 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0.
|
19
|
+
version: '0.69'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0.
|
26
|
+
version: '0.69'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: qeweney
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0.
|
33
|
+
version: '0.14'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '0.
|
40
|
+
version: '0.14'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: extralite
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: '1.2'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: '1.2'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: http-2
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 0.
|
61
|
+
version: '0.11'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 0.
|
68
|
+
version: '0.11'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rack
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,6 +114,20 @@ dependencies:
|
|
114
114
|
- - "~>"
|
115
115
|
- !ruby/object:Gem::Version
|
116
116
|
version: 2.0.8
|
117
|
+
- !ruby/object:Gem::Dependency
|
118
|
+
name: localhost
|
119
|
+
requirement: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - "~>"
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: 1.1.4
|
124
|
+
type: :runtime
|
125
|
+
prerelease: false
|
126
|
+
version_requirements: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - "~>"
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: 1.1.4
|
117
131
|
- !ruby/object:Gem::Dependency
|
118
132
|
name: msgpack
|
119
133
|
requirement: !ruby/object:Gem::Requirement
|
@@ -156,20 +170,6 @@ dependencies:
|
|
156
170
|
- - "~>"
|
157
171
|
- !ruby/object:Gem::Version
|
158
172
|
version: 12.3.3
|
159
|
-
- !ruby/object:Gem::Dependency
|
160
|
-
name: localhost
|
161
|
-
requirement: !ruby/object:Gem::Requirement
|
162
|
-
requirements:
|
163
|
-
- - "~>"
|
164
|
-
- !ruby/object:Gem::Version
|
165
|
-
version: 1.1.4
|
166
|
-
type: :development
|
167
|
-
prerelease: false
|
168
|
-
version_requirements: !ruby/object:Gem::Requirement
|
169
|
-
requirements:
|
170
|
-
- - "~>"
|
171
|
-
- !ruby/object:Gem::Version
|
172
|
-
version: 1.1.4
|
173
173
|
- !ruby/object:Gem::Dependency
|
174
174
|
name: minitest
|
175
175
|
requirement: !ruby/object:Gem::Requirement
|
@@ -226,6 +226,20 @@ dependencies:
|
|
226
226
|
- - "~>"
|
227
227
|
- !ruby/object:Gem::Version
|
228
228
|
version: 3.9.3
|
229
|
+
- !ruby/object:Gem::Dependency
|
230
|
+
name: http_parser.rb
|
231
|
+
requirement: !ruby/object:Gem::Requirement
|
232
|
+
requirements:
|
233
|
+
- - '='
|
234
|
+
- !ruby/object:Gem::Version
|
235
|
+
version: 0.7.0
|
236
|
+
type: :development
|
237
|
+
prerelease: false
|
238
|
+
version_requirements: !ruby/object:Gem::Requirement
|
239
|
+
requirements:
|
240
|
+
- - '='
|
241
|
+
- !ruby/object:Gem::Version
|
242
|
+
version: 0.7.0
|
229
243
|
description:
|
230
244
|
email: sharon@noteflakes.com
|
231
245
|
executables:
|
@@ -244,6 +258,9 @@ files:
|
|
244
258
|
- README.md
|
245
259
|
- Rakefile
|
246
260
|
- TODO.md
|
261
|
+
- benchmarks/bm_http1_parser.rb
|
262
|
+
- bin/benchmark
|
263
|
+
- bin/h1pd
|
247
264
|
- bin/tipi
|
248
265
|
- df/agent.rb
|
249
266
|
- df/etc_benchmark.rb
|
@@ -258,8 +275,8 @@ files:
|
|
258
275
|
- df/ws_page.html
|
259
276
|
- docs/README.md
|
260
277
|
- docs/tipi-logo.png
|
261
|
-
- examples/automatic_certificate.rb
|
262
278
|
- examples/cuba.ru
|
279
|
+
- examples/full_service.rb
|
263
280
|
- examples/hanami-api.ru
|
264
281
|
- examples/hello.ru
|
265
282
|
- examples/http1_parser.rb
|
@@ -284,6 +301,7 @@ files:
|
|
284
301
|
- examples/rack_server_https.rb
|
285
302
|
- examples/rack_server_https_forked.rb
|
286
303
|
- examples/routing_server.rb
|
304
|
+
- examples/servername_cb.rb
|
287
305
|
- examples/websocket_client.rb
|
288
306
|
- examples/websocket_demo.rb
|
289
307
|
- examples/websocket_secure_server.rb
|
@@ -295,6 +313,8 @@ files:
|
|
295
313
|
- ext/tipi/http1_parser.h
|
296
314
|
- ext/tipi/tipi_ext.c
|
297
315
|
- lib/tipi.rb
|
316
|
+
- lib/tipi/acme.rb
|
317
|
+
- lib/tipi/cli.rb
|
298
318
|
- lib/tipi/config_dsl.rb
|
299
319
|
- lib/tipi/configuration.rb
|
300
320
|
- lib/tipi/digital_fabric.rb
|
@@ -307,17 +327,18 @@ files:
|
|
307
327
|
- lib/tipi/digital_fabric/service.rb
|
308
328
|
- lib/tipi/handler.rb
|
309
329
|
- lib/tipi/http1_adapter.rb
|
310
|
-
- lib/tipi/http1_adapter_new.rb
|
311
330
|
- lib/tipi/http2_adapter.rb
|
312
331
|
- lib/tipi/http2_stream.rb
|
313
332
|
- lib/tipi/rack_adapter.rb
|
314
333
|
- lib/tipi/response_extensions.rb
|
315
334
|
- lib/tipi/version.rb
|
316
335
|
- lib/tipi/websocket.rb
|
336
|
+
- security/http1.rb
|
317
337
|
- test/coverage.rb
|
318
338
|
- test/eg.rb
|
319
339
|
- test/helper.rb
|
320
340
|
- test/run.rb
|
341
|
+
- test/test_http1_parser.rb
|
321
342
|
- test/test_http_server.rb
|
322
343
|
- test/test_request.rb
|
323
344
|
- tipi.gemspec
|
@@ -1,193 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'bundler/setup'
|
4
|
-
require 'tipi'
|
5
|
-
require 'openssl'
|
6
|
-
require 'acme-client'
|
7
|
-
|
8
|
-
# ::Exception.__disable_sanitized_backtrace__ = true
|
9
|
-
|
10
|
-
class CertificateManager
|
11
|
-
def initialize(store:, challenge_handler:)
|
12
|
-
@store = store
|
13
|
-
@challenge_handler = challenge_handler
|
14
|
-
@workers = {}
|
15
|
-
@contexts = {}
|
16
|
-
end
|
17
|
-
|
18
|
-
def [](name)
|
19
|
-
worker = worker_for_name(name)
|
20
|
-
p worker: worker
|
21
|
-
|
22
|
-
worker << Fiber.current
|
23
|
-
# cancel_after(30) { receive }
|
24
|
-
receive.tap { |ctx| p got_ctx: ctx }
|
25
|
-
rescue Exception => e
|
26
|
-
p e
|
27
|
-
puts e.backtrace.join("\n")
|
28
|
-
nil
|
29
|
-
end
|
30
|
-
|
31
|
-
def worker_for_name(name)
|
32
|
-
@workers[name] ||= spin { worker_loop(name) }
|
33
|
-
end
|
34
|
-
|
35
|
-
def worker_loop(name)
|
36
|
-
while (client = receive)
|
37
|
-
puts "get request for #{name} from #{client.inspect}"
|
38
|
-
ctx = get_context(name)
|
39
|
-
client << ctx rescue nil
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def get_context(name)
|
44
|
-
@contexts[name] ||= setup_context(name)
|
45
|
-
end
|
46
|
-
|
47
|
-
CERTIFICATE_REGEXP = /(-----BEGIN CERTIFICATE-----\n[^-]+-----END CERTIFICATE-----\n)/.freeze
|
48
|
-
|
49
|
-
def setup_context(name)
|
50
|
-
certificate = get_certificate(name)
|
51
|
-
ctx = OpenSSL::SSL::SSLContext.new
|
52
|
-
chain = certificate.scan(CERTIFICATE_REGEXP).map { |p| OpenSSL::X509::Certificate.new(p.first) }
|
53
|
-
cert = chain.shift
|
54
|
-
puts "Certificate expires: #{cert.not_after.inspect}"
|
55
|
-
ctx.add_certificate(cert, private_key, chain)
|
56
|
-
Polyphony::Net.setup_alpn(ctx, Tipi::ALPN_PROTOCOLS)
|
57
|
-
ctx
|
58
|
-
end
|
59
|
-
|
60
|
-
def get_certificate(name)
|
61
|
-
@store[name] ||= provision_certificate(name)
|
62
|
-
end
|
63
|
-
|
64
|
-
def private_key
|
65
|
-
@private_key ||= OpenSSL::PKey::RSA.new(4096)
|
66
|
-
end
|
67
|
-
|
68
|
-
ACME_DIRECTORY = 'https://acme-staging-v02.api.letsencrypt.org/directory'
|
69
|
-
|
70
|
-
def acme_client
|
71
|
-
@acme_client ||= setup_acme_client
|
72
|
-
end
|
73
|
-
|
74
|
-
def setup_acme_client
|
75
|
-
client = Acme::Client.new(
|
76
|
-
private_key: private_key,
|
77
|
-
directory: ACME_DIRECTORY
|
78
|
-
)
|
79
|
-
p client: client
|
80
|
-
account = client.new_account(
|
81
|
-
contact: 'mailto:info@noteflakes.com',
|
82
|
-
terms_of_service_agreed: true
|
83
|
-
)
|
84
|
-
p account: account.kid
|
85
|
-
client
|
86
|
-
end
|
87
|
-
|
88
|
-
def provision_certificate(name)
|
89
|
-
order = acme_client.new_order(identifiers: [name])
|
90
|
-
p order: true
|
91
|
-
authorization = order.authorizations.first
|
92
|
-
p authorization: authorization
|
93
|
-
challenge = authorization.http
|
94
|
-
p challenge: challenge
|
95
|
-
|
96
|
-
@challenge_handler.add(challenge)
|
97
|
-
challenge.request_validation
|
98
|
-
p challenge_status: challenge.status
|
99
|
-
while challenge.status == 'pending'
|
100
|
-
sleep(1)
|
101
|
-
challenge.reload
|
102
|
-
p challenge_status: challenge.status
|
103
|
-
end
|
104
|
-
|
105
|
-
csr = Acme::Client::CertificateRequest.new(private_key: @private_key, subject: { common_name: name })
|
106
|
-
p csr: csr
|
107
|
-
order.finalize(csr: csr)
|
108
|
-
p order_status: order.status
|
109
|
-
while order.status == 'processing'
|
110
|
-
sleep(1)
|
111
|
-
order.reload
|
112
|
-
p order_status: order.status
|
113
|
-
end
|
114
|
-
order.certificate.tap { |c| p certificate: c } # => PEM-formatted certificate
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
class AcmeHTTPChallengeHandler
|
119
|
-
def initialize
|
120
|
-
@challenges = {}
|
121
|
-
end
|
122
|
-
|
123
|
-
def add(challenge)
|
124
|
-
path = "/.well-known/acme-challenge/#{challenge.token}"
|
125
|
-
@challenges[path] = challenge
|
126
|
-
end
|
127
|
-
|
128
|
-
def call(req)
|
129
|
-
# handle incoming request
|
130
|
-
challenge = @challenges[req.path]
|
131
|
-
return req.respond(nil, ':status' => 400) unless challenge
|
132
|
-
|
133
|
-
req.respond(challenge.file_content, 'content-type' => challenge.content_type)
|
134
|
-
@challenges.delete(req.path)
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
challenge_handler = AcmeHTTPChallengeHandler.new
|
139
|
-
certificate_manager = CertificateManager.new(
|
140
|
-
store: {},
|
141
|
-
challenge_handler: challenge_handler
|
142
|
-
)
|
143
|
-
|
144
|
-
http_handler = Tipi.route do |r|
|
145
|
-
r.on('/.well-known/acme-challenge') { challenge_handler.call(r) }
|
146
|
-
r.default { r.redirect "https://#{r.host}#{r.path}" }
|
147
|
-
end
|
148
|
-
|
149
|
-
https_handler = ->(r) { r.respond('Hello, world!') }
|
150
|
-
|
151
|
-
http_listener = spin do
|
152
|
-
opts = {
|
153
|
-
reuse_addr: true,
|
154
|
-
dont_linger: true,
|
155
|
-
}
|
156
|
-
puts 'Listening for HTTP on localhost:10080'
|
157
|
-
Tipi.serve('0.0.0.0', 10080, opts, &http_handler)
|
158
|
-
end
|
159
|
-
|
160
|
-
https_listener = spin do
|
161
|
-
ctx = OpenSSL::SSL::SSLContext.new
|
162
|
-
ctx.servername_cb = proc { |_, name| p name: name; certificate_manager[name] }
|
163
|
-
opts = {
|
164
|
-
reuse_addr: true,
|
165
|
-
dont_linger: true,
|
166
|
-
secure_context: ctx,
|
167
|
-
alpn_protocols: Tipi::ALPN_PROTOCOLS
|
168
|
-
}
|
169
|
-
|
170
|
-
puts 'Listening for HTTPS on localhost:10443'
|
171
|
-
server = Polyphony::Net.tcp_listen('0.0.0.0', 10443, opts)
|
172
|
-
server.accept_loop do |client|
|
173
|
-
spin do
|
174
|
-
service.incr_connection_count
|
175
|
-
Tipi.client_loop(client, opts) { |req| service.http_request(req) }
|
176
|
-
ensure
|
177
|
-
service.decr_connection_count
|
178
|
-
end
|
179
|
-
rescue Exception => e
|
180
|
-
puts "HTTPS accept_loop error: #{e.inspect}"
|
181
|
-
puts e.backtrace.join("\n")
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
begin
|
186
|
-
Fiber.await(http_listener, https_listener)
|
187
|
-
rescue Interrupt
|
188
|
-
puts "Got SIGINT, terminating"
|
189
|
-
rescue Exception => e
|
190
|
-
puts '*' * 40
|
191
|
-
p e
|
192
|
-
puts e.backtrace.join("\n")
|
193
|
-
end
|