rage-iodine 1.7.58
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
- data/.github/workflows/ruby.yml +42 -0
- data/.gitignore +20 -0
- data/.rspec +2 -0
- data/.yardopts +8 -0
- data/CHANGELOG.md +1098 -0
- data/Gemfile +11 -0
- data/LICENSE.txt +21 -0
- data/LIMITS.md +41 -0
- data/README.md +782 -0
- data/Rakefile +23 -0
- data/SPEC-PubSub-Draft.md +159 -0
- data/SPEC-WebSocket-Draft.md +239 -0
- data/bin/console +22 -0
- data/bin/info.md +353 -0
- data/bin/mustache_bench.rb +100 -0
- data/bin/poc/Gemfile.lock +23 -0
- data/bin/poc/README.md +37 -0
- data/bin/poc/config.ru +66 -0
- data/bin/poc/gemfile +1 -0
- data/bin/poc/www/index.html +57 -0
- data/examples/async_task.ru +92 -0
- data/examples/bates/README.md +3 -0
- data/examples/bates/config.ru +342 -0
- data/examples/bates/david+bold.pdf +0 -0
- data/examples/bates/public/drop-pdf.png +0 -0
- data/examples/bates/public/index.html +600 -0
- data/examples/config.ru +59 -0
- data/examples/echo.ru +59 -0
- data/examples/etag.ru +16 -0
- data/examples/hello.ru +29 -0
- data/examples/pubsub_engine.ru +81 -0
- data/examples/rack3.ru +12 -0
- data/examples/redis.ru +70 -0
- data/examples/shootout.ru +73 -0
- data/examples/sub-protocols.ru +90 -0
- data/examples/tcp_client.rb +66 -0
- data/examples/x-sendfile.ru +14 -0
- data/exe/iodine +280 -0
- data/ext/iodine/extconf.rb +110 -0
- data/ext/iodine/fio.c +12096 -0
- data/ext/iodine/fio.h +6390 -0
- data/ext/iodine/fio_cli.c +431 -0
- data/ext/iodine/fio_cli.h +189 -0
- data/ext/iodine/fio_json_parser.h +687 -0
- data/ext/iodine/fio_siphash.c +157 -0
- data/ext/iodine/fio_siphash.h +37 -0
- data/ext/iodine/fio_tls.h +129 -0
- data/ext/iodine/fio_tls_missing.c +649 -0
- data/ext/iodine/fio_tls_openssl.c +1056 -0
- data/ext/iodine/fio_tmpfile.h +50 -0
- data/ext/iodine/fiobj.h +44 -0
- data/ext/iodine/fiobj4fio.h +21 -0
- data/ext/iodine/fiobj_ary.c +333 -0
- data/ext/iodine/fiobj_ary.h +139 -0
- data/ext/iodine/fiobj_data.c +1185 -0
- data/ext/iodine/fiobj_data.h +167 -0
- data/ext/iodine/fiobj_hash.c +409 -0
- data/ext/iodine/fiobj_hash.h +176 -0
- data/ext/iodine/fiobj_json.c +622 -0
- data/ext/iodine/fiobj_json.h +68 -0
- data/ext/iodine/fiobj_mem.h +71 -0
- data/ext/iodine/fiobj_mustache.c +317 -0
- data/ext/iodine/fiobj_mustache.h +62 -0
- data/ext/iodine/fiobj_numbers.c +344 -0
- data/ext/iodine/fiobj_numbers.h +127 -0
- data/ext/iodine/fiobj_str.c +433 -0
- data/ext/iodine/fiobj_str.h +172 -0
- data/ext/iodine/fiobject.c +620 -0
- data/ext/iodine/fiobject.h +654 -0
- data/ext/iodine/hpack.h +1923 -0
- data/ext/iodine/http.c +2736 -0
- data/ext/iodine/http.h +1019 -0
- data/ext/iodine/http1.c +825 -0
- data/ext/iodine/http1.h +29 -0
- data/ext/iodine/http1_parser.h +1835 -0
- data/ext/iodine/http_internal.c +1279 -0
- data/ext/iodine/http_internal.h +248 -0
- data/ext/iodine/http_mime_parser.h +350 -0
- data/ext/iodine/iodine.c +1433 -0
- data/ext/iodine/iodine.h +64 -0
- data/ext/iodine/iodine_caller.c +218 -0
- data/ext/iodine/iodine_caller.h +27 -0
- data/ext/iodine/iodine_connection.c +941 -0
- data/ext/iodine/iodine_connection.h +55 -0
- data/ext/iodine/iodine_defer.c +420 -0
- data/ext/iodine/iodine_defer.h +6 -0
- data/ext/iodine/iodine_fiobj2rb.h +120 -0
- data/ext/iodine/iodine_helpers.c +282 -0
- data/ext/iodine/iodine_helpers.h +12 -0
- data/ext/iodine/iodine_http.c +1280 -0
- data/ext/iodine/iodine_http.h +23 -0
- data/ext/iodine/iodine_json.c +302 -0
- data/ext/iodine/iodine_json.h +6 -0
- data/ext/iodine/iodine_mustache.c +567 -0
- data/ext/iodine/iodine_mustache.h +6 -0
- data/ext/iodine/iodine_pubsub.c +580 -0
- data/ext/iodine/iodine_pubsub.h +26 -0
- data/ext/iodine/iodine_rack_io.c +273 -0
- data/ext/iodine/iodine_rack_io.h +20 -0
- data/ext/iodine/iodine_store.c +142 -0
- data/ext/iodine/iodine_store.h +20 -0
- data/ext/iodine/iodine_tcp.c +346 -0
- data/ext/iodine/iodine_tcp.h +13 -0
- data/ext/iodine/iodine_tls.c +261 -0
- data/ext/iodine/iodine_tls.h +13 -0
- data/ext/iodine/mustache_parser.h +1546 -0
- data/ext/iodine/redis_engine.c +957 -0
- data/ext/iodine/redis_engine.h +79 -0
- data/ext/iodine/resp_parser.h +317 -0
- data/ext/iodine/scheduler.c +173 -0
- data/ext/iodine/scheduler.h +6 -0
- data/ext/iodine/websocket_parser.h +506 -0
- data/ext/iodine/websockets.c +752 -0
- data/ext/iodine/websockets.h +185 -0
- data/iodine.gemspec +50 -0
- data/lib/iodine/connection.rb +61 -0
- data/lib/iodine/json.rb +42 -0
- data/lib/iodine/mustache.rb +113 -0
- data/lib/iodine/pubsub.rb +55 -0
- data/lib/iodine/rack_utils.rb +43 -0
- data/lib/iodine/tls.rb +16 -0
- data/lib/iodine/version.rb +3 -0
- data/lib/iodine.rb +274 -0
- data/lib/rack/handler/iodine.rb +33 -0
- data/logo.png +0 -0
- metadata +284 -0
data/exe/iodine
ADDED
@@ -0,0 +1,280 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
IODINE_PARSE_CLI = true
|
4
|
+
require 'iodine'
|
5
|
+
|
6
|
+
# Load Rack if available (assume it will be used).
|
7
|
+
#
|
8
|
+
# Remember, code costs memory. Duplicating the Rack::Builder module and functions can be avoided.
|
9
|
+
begin
|
10
|
+
require 'rack'
|
11
|
+
module Iodine
|
12
|
+
module Base
|
13
|
+
module Rack
|
14
|
+
Builder = ::Rack::Builder
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
rescue LoadError
|
19
|
+
puts "WARNING: The gam `rack` wasn't loaded before iodine started loading the rack app, using custom loader."
|
20
|
+
module Iodine
|
21
|
+
module Base
|
22
|
+
module Rack
|
23
|
+
# The Rack::Builder code is used when Rack isn't available.
|
24
|
+
#
|
25
|
+
# The code was copied (with minor adjustments) from the Rack source code and is licensed under the MIT license.
|
26
|
+
# Copyright (C) 2007-2019 Leah Neukirchen <http://leahneukirchen.org/infopage.html>
|
27
|
+
#
|
28
|
+
# ====
|
29
|
+
#
|
30
|
+
# Rack::Builder implements a small DSL to iteratively construct Rack
|
31
|
+
# applications.
|
32
|
+
#
|
33
|
+
# Example:
|
34
|
+
#
|
35
|
+
# require 'rack/lobster'
|
36
|
+
# app = Rack::Builder.new do
|
37
|
+
# use Rack::CommonLogger
|
38
|
+
# use Rack::ShowExceptions
|
39
|
+
# map "/lobster" do
|
40
|
+
# use Rack::Lint
|
41
|
+
# run Rack::Lobster.new
|
42
|
+
# end
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# run app
|
46
|
+
#
|
47
|
+
# Or
|
48
|
+
#
|
49
|
+
# app = Rack::Builder.app do
|
50
|
+
# use Rack::CommonLogger
|
51
|
+
# run lambda { |env| [200, {'Content-Type' => 'text/plain'}, ['OK']] }
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# run app
|
55
|
+
#
|
56
|
+
# +use+ adds middleware to the stack, +run+ dispatches to an application.
|
57
|
+
# You can use +map+ to construct a Rack::URLMap in a convenient way.
|
58
|
+
class Builder
|
59
|
+
# https://stackoverflow.com/questions/2223882/whats-the-difference-between-utf-8-and-utf-8-without-bom
|
60
|
+
UTF_8_BOM = '\xef\xbb\xbf'
|
61
|
+
|
62
|
+
def self.parse_file(config, opts = Hash.new)
|
63
|
+
if config =~ /\.ru$/
|
64
|
+
return self.load_file(config, opts)
|
65
|
+
else
|
66
|
+
require config
|
67
|
+
app = Object.const_get(::File.basename(config, '.rb').split('_').map(&:capitalize).join(''))
|
68
|
+
return app, {}
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.load_file(path, options = Hash.new)
|
73
|
+
cfgfile = ::File.read(path)
|
74
|
+
cfgfile.slice!(/\A#{UTF_8_BOM}/) if cfgfile.encoding == Encoding::UTF_8
|
75
|
+
|
76
|
+
cfgfile.sub!(/^__END__\n.*\Z/m, '')
|
77
|
+
app = new_from_string cfgfile, path
|
78
|
+
|
79
|
+
return app, options
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.new_from_string(builder_script, file = "(rackup)")
|
83
|
+
eval "Iodine::Base::Rack::Builder.new {\n" + builder_script + "\n}.to_app",
|
84
|
+
TOPLEVEL_BINDING, file, 0
|
85
|
+
end
|
86
|
+
|
87
|
+
def initialize(default_app = nil, &block)
|
88
|
+
@use, @map, @run, @warmup, @freeze_app = [], nil, default_app, nil, false
|
89
|
+
instance_eval(&block) if block_given?
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.app(default_app = nil, &block)
|
93
|
+
self.new(default_app, &block).to_app
|
94
|
+
end
|
95
|
+
|
96
|
+
# Specifies middleware to use in a stack.
|
97
|
+
#
|
98
|
+
# class Middleware
|
99
|
+
# def initialize(app)
|
100
|
+
# @app = app
|
101
|
+
# end
|
102
|
+
#
|
103
|
+
# def call(env)
|
104
|
+
# env["rack.some_header"] = "setting an example"
|
105
|
+
# @app.call(env)
|
106
|
+
# end
|
107
|
+
# end
|
108
|
+
#
|
109
|
+
# use Middleware
|
110
|
+
# run lambda { |env| [200, { "Content-Type" => "text/plain" }, ["OK"]] }
|
111
|
+
#
|
112
|
+
# All requests through to this application will first be processed by the middleware class.
|
113
|
+
# The +call+ method in this example sets an additional environment key which then can be
|
114
|
+
# referenced in the application if required.
|
115
|
+
def use(middleware, *args, &block)
|
116
|
+
if @map
|
117
|
+
mapping, @map = @map, nil
|
118
|
+
@use << proc { |app| generate_map(app, mapping) }
|
119
|
+
end
|
120
|
+
@use << proc { |app| middleware.new(app, *args, &block) }
|
121
|
+
end
|
122
|
+
|
123
|
+
# Takes an argument that is an object that responds to #call and returns a Rack response.
|
124
|
+
# The simplest form of this is a lambda object:
|
125
|
+
#
|
126
|
+
# run lambda { |env| [200, { "Content-Type" => "text/plain" }, ["OK"]] }
|
127
|
+
#
|
128
|
+
# However this could also be a class:
|
129
|
+
#
|
130
|
+
# class Heartbeat
|
131
|
+
# def self.call(env)
|
132
|
+
# [200, { "Content-Type" => "text/plain" }, ["OK"]]
|
133
|
+
# end
|
134
|
+
# end
|
135
|
+
#
|
136
|
+
# run Heartbeat
|
137
|
+
def run(app = nil, &block)
|
138
|
+
raise ArgumentError, "Both app and block given!" if app && block_given?
|
139
|
+
@run = app || block
|
140
|
+
end
|
141
|
+
|
142
|
+
# Takes a lambda or block that is used to warm-up the application.
|
143
|
+
#
|
144
|
+
# warmup do |app|
|
145
|
+
# client = Rack::MockRequest.new(app)
|
146
|
+
# client.get('/')
|
147
|
+
# end
|
148
|
+
#
|
149
|
+
# use SomeMiddleware
|
150
|
+
# run MyApp
|
151
|
+
def warmup(prc = nil, &block)
|
152
|
+
@warmup = prc || block
|
153
|
+
end
|
154
|
+
|
155
|
+
# Creates a route within the application.
|
156
|
+
#
|
157
|
+
# Rack::Builder.app do
|
158
|
+
# map '/' do
|
159
|
+
# run Heartbeat
|
160
|
+
# end
|
161
|
+
# end
|
162
|
+
#
|
163
|
+
# The +use+ method can also be used here to specify middleware to run under a specific path:
|
164
|
+
#
|
165
|
+
# Rack::Builder.app do
|
166
|
+
# map '/' do
|
167
|
+
# use Middleware
|
168
|
+
# run Heartbeat
|
169
|
+
# end
|
170
|
+
# end
|
171
|
+
#
|
172
|
+
# This example includes a piece of middleware which will run before requests hit +Heartbeat+.
|
173
|
+
#
|
174
|
+
def map(path, &block)
|
175
|
+
@map ||= {}
|
176
|
+
@map[path] = block
|
177
|
+
end
|
178
|
+
|
179
|
+
# Freeze the app (set using run) and all middleware instances when building the application
|
180
|
+
# in to_app.
|
181
|
+
def freeze_app
|
182
|
+
@freeze_app = true
|
183
|
+
end
|
184
|
+
|
185
|
+
def to_app
|
186
|
+
app = @map ? generate_map(@run, @map) : @run
|
187
|
+
fail "missing run or map statement" unless app
|
188
|
+
app.freeze if @freeze_app
|
189
|
+
app = @use.reverse.inject(app) { |a, e| e[a].tap { |x| x.freeze if @freeze_app } }
|
190
|
+
@warmup.call(app) if @warmup
|
191
|
+
app
|
192
|
+
end
|
193
|
+
|
194
|
+
def call(env)
|
195
|
+
to_app.call(env)
|
196
|
+
end
|
197
|
+
|
198
|
+
private
|
199
|
+
|
200
|
+
def generate_map(default_app, mapping)
|
201
|
+
mapped = default_app ? { '/' => default_app } : {}
|
202
|
+
mapping.each { |r, b| mapped[r] = self.class.new(default_app, &b).to_app }
|
203
|
+
URLMap.new(mapped)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
module Iodine
|
212
|
+
# The Iodine::Base namespace is reserved for internal use and is NOT part of the public API.
|
213
|
+
module Base
|
214
|
+
# Command line interface. The Ruby CLI might be changed in future versions.
|
215
|
+
module CLI
|
216
|
+
|
217
|
+
def self.try_file filename
|
218
|
+
return nil unless File.exist? filename
|
219
|
+
result = Iodine::Base::Rack::Builder.parse_file filename
|
220
|
+
return result[0] if(result.is_a?(Array))
|
221
|
+
return result
|
222
|
+
end
|
223
|
+
|
224
|
+
def self.get_app_opts
|
225
|
+
app, opt = nil, Hash.new
|
226
|
+
filename = Iodine::DEFAULT_SETTINGS[:filename_]
|
227
|
+
if filename
|
228
|
+
app = try_file(filename)
|
229
|
+
app = try_file("#{filename}.ru") unless app
|
230
|
+
unless app
|
231
|
+
puts "* Couldn't find #{filename}\n testing for config.ru\n"
|
232
|
+
app = try_file "config.ru"
|
233
|
+
end
|
234
|
+
else
|
235
|
+
app = try_file "config.ru";
|
236
|
+
end
|
237
|
+
|
238
|
+
unless app
|
239
|
+
puts "WARNING: Ruby application not found#{ filename ? " - missing both #{filename} and config.ru" : " - missing config.ru"}."
|
240
|
+
if Iodine::DEFAULT_SETTINGS[:public]
|
241
|
+
puts " Running only static file service."
|
242
|
+
app = Proc.new { [404, {}, "Not Found!"] }
|
243
|
+
else
|
244
|
+
puts "\nERROR: Couldn't run Ruby application, check command line arguments."
|
245
|
+
ARGV << "-?"
|
246
|
+
Iodine::Base::CLI.parse
|
247
|
+
exit(0);
|
248
|
+
end
|
249
|
+
end
|
250
|
+
return app, opt
|
251
|
+
end
|
252
|
+
|
253
|
+
def self.perform_warmup(app)
|
254
|
+
# load anything marked with `autoload`, since autoload is niether thread safe nor fork friendly.
|
255
|
+
Iodine.on_state(:on_start) do
|
256
|
+
Module.constants.each do |n|
|
257
|
+
begin
|
258
|
+
Object.const_get(n)
|
259
|
+
rescue StandardError => _e
|
260
|
+
end
|
261
|
+
end
|
262
|
+
Iodine::Base::Rack::Builder.new(app) do |r|
|
263
|
+
r.warmup do |a|
|
264
|
+
client = ::Rack::MockRequest.new(a)
|
265
|
+
client.get('/')
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
def self.call
|
272
|
+
app, opt = get_app_opts
|
273
|
+
perform_warmup(app) if Iodine::DEFAULT_SETTINGS[:warmup_]
|
274
|
+
Iodine::Rack.run(app, opt)
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
Iodine::Base::CLI.call
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
# Test polling
|
5
|
+
def iodine_test_polling_support
|
6
|
+
iodine_poll_test_kqueue = <<EOS
|
7
|
+
\#define _GNU_SOURCE
|
8
|
+
\#include <stdlib.h>
|
9
|
+
\#include <sys/event.h>
|
10
|
+
int main(void) {
|
11
|
+
int fd = kqueue();
|
12
|
+
}
|
13
|
+
EOS
|
14
|
+
|
15
|
+
iodine_poll_test_epoll = <<EOS
|
16
|
+
\#define _GNU_SOURCE
|
17
|
+
\#include <stdlib.h>
|
18
|
+
\#include <stdio.h>
|
19
|
+
\#include <sys/types.h>
|
20
|
+
\#include <sys/stat.h>
|
21
|
+
\#include <fcntl.h>
|
22
|
+
\#include <sys/epoll.h>
|
23
|
+
int main(void) {
|
24
|
+
int fd = epoll_create1(EPOLL_CLOEXEC);
|
25
|
+
}
|
26
|
+
EOS
|
27
|
+
|
28
|
+
iodine_poll_test_poll = <<EOS
|
29
|
+
\#define _GNU_SOURCE
|
30
|
+
\#include <stdlib.h>
|
31
|
+
\#include <poll.h>
|
32
|
+
int main(void) {
|
33
|
+
struct pollfd plist[18];
|
34
|
+
memset(plist, 0, sizeof(plist[0]) * 18);
|
35
|
+
poll(plist, 1, 1);
|
36
|
+
}
|
37
|
+
EOS
|
38
|
+
|
39
|
+
# Test for manual selection and then TRY_COMPILE with each polling engine
|
40
|
+
if Gem.win_platform?
|
41
|
+
puts "skipping polling tests, using WSAPOLL on Windows"
|
42
|
+
$defs << "-DFIO_ENGINE_WSAPOLL"
|
43
|
+
elsif ENV['FIO_POLL']
|
44
|
+
puts "skipping polling tests, enforcing manual selection of: poll"
|
45
|
+
$defs << "-DFIO_ENGINE_POLL"
|
46
|
+
elsif ENV['FIO_FORCE_POLL']
|
47
|
+
puts "skipping polling tests, enforcing manual selection of: poll"
|
48
|
+
$defs << "-DFIO_ENGINE_POLL"
|
49
|
+
elsif ENV['FIO_FORCE_EPOLL']
|
50
|
+
puts "skipping polling tests, enforcing manual selection of: epoll"
|
51
|
+
$defs << "-DFIO_ENGINE_EPOLL"
|
52
|
+
elsif ENV['FIO_FORCE_KQUEUE']
|
53
|
+
puts "* Skipping polling tests, enforcing manual selection of: kqueue"
|
54
|
+
$defs << "-DFIO_ENGINE_KQUEUE"
|
55
|
+
elsif try_compile(iodine_poll_test_epoll)
|
56
|
+
puts "detected `epoll`"
|
57
|
+
$defs << "-DFIO_ENGINE_EPOLL"
|
58
|
+
elsif try_compile(iodine_poll_test_kqueue)
|
59
|
+
puts "detected `kqueue`"
|
60
|
+
$defs << "-DFIO_ENGINE_KQUEUE"
|
61
|
+
elsif try_compile(iodine_poll_test_poll)
|
62
|
+
puts "detected `poll` - this is suboptimal fallback!"
|
63
|
+
$defs << "-DFIO_ENGINE_POLL"
|
64
|
+
else
|
65
|
+
puts "* WARNING: No supported polling engine! expecting compilation to fail."
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
iodine_test_polling_support()
|
70
|
+
|
71
|
+
unless Gem.win_platform?
|
72
|
+
# Test for OpenSSL version equal to 1.0.0 or greater.
|
73
|
+
unless ENV['NO_SSL'] || ENV['NO_TLS'] || ENV["DISABLE_SSL"]
|
74
|
+
OPENSSL_TEST_CODE = <<EOS
|
75
|
+
\#include <openssl/bio.h>
|
76
|
+
\#include <openssl/err.h>
|
77
|
+
\#include <openssl/ssl.h>
|
78
|
+
\#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
79
|
+
\#error "OpenSSL version too small"
|
80
|
+
\#endif
|
81
|
+
int main(void) {
|
82
|
+
SSL_library_init();
|
83
|
+
SSL_CTX *ctx = SSL_CTX_new(TLS_method());
|
84
|
+
SSL *ssl = SSL_new(ctx);
|
85
|
+
BIO *bio = BIO_new_socket(3, 0);
|
86
|
+
BIO_up_ref(bio);
|
87
|
+
SSL_set0_rbio(ssl, bio);
|
88
|
+
SSL_set0_wbio(ssl, bio);
|
89
|
+
}
|
90
|
+
EOS
|
91
|
+
|
92
|
+
dir_config("openssl")
|
93
|
+
begin
|
94
|
+
require 'openssl'
|
95
|
+
rescue LoadError
|
96
|
+
else
|
97
|
+
if have_library('crypto') && have_library('ssl')
|
98
|
+
puts "detected OpenSSL library, testing for version and required functions."
|
99
|
+
if try_compile(OPENSSL_TEST_CODE)
|
100
|
+
$defs << "-DHAVE_OPENSSL"
|
101
|
+
puts "confirmed OpenSSL to be version 1.1.0 or above (#{OpenSSL::OPENSSL_LIBRARY_VERSION})...\n* compiling with HAVE_OPENSSL."
|
102
|
+
else
|
103
|
+
puts "FAILED: OpenSSL version not supported (#{OpenSSL::OPENSSL_LIBRARY_VERSION} is too old)."
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
create_makefile 'iodine/iodine_ext'
|