eventmachine 1.0.9.1-java → 1.2.0.1-java
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/CHANGELOG.md +26 -0
- data/README.md +2 -2
- data/ext/cmain.cpp +77 -5
- data/ext/ed.cpp +112 -42
- data/ext/ed.h +27 -13
- data/ext/em.cpp +105 -163
- data/ext/em.h +10 -7
- data/ext/eventmachine.h +13 -1
- data/ext/extconf.rb +23 -14
- data/ext/fastfilereader/extconf.rb +1 -2
- data/ext/fastfilereader/rubymain.cpp +6 -6
- data/ext/project.h +9 -4
- data/ext/rubymain.cpp +155 -36
- data/ext/ssl.cpp +157 -13
- data/ext/ssl.h +7 -2
- data/lib/em/channel.rb +5 -0
- data/lib/em/completion.rb +2 -2
- data/lib/em/connection.rb +61 -3
- data/lib/em/iterator.rb +26 -5
- data/lib/em/pool.rb +1 -1
- data/lib/em/protocols/line_and_text.rb +1 -1
- data/lib/em/pure_ruby.rb +6 -1
- data/lib/em/queue.rb +16 -7
- data/lib/em/resolver.rb +46 -23
- data/lib/em/threaded_resource.rb +2 -2
- data/lib/em/version.rb +1 -1
- data/lib/eventmachine.rb +59 -42
- data/lib/rubyeventmachine.jar +0 -0
- data/rakelib/package.rake +23 -1
- data/tests/dhparam.pem +13 -0
- data/tests/em_test_helper.rb +79 -0
- data/tests/test_basic.rb +17 -26
- data/tests/test_channel.rb +14 -1
- data/tests/test_connection_write.rb +2 -2
- data/tests/test_defer.rb +17 -0
- data/tests/test_epoll.rb +1 -1
- data/tests/test_fork.rb +75 -0
- data/tests/test_ipv4.rb +125 -0
- data/tests/test_ipv6.rb +131 -0
- data/tests/test_iterator.rb +18 -0
- data/tests/test_many_fds.rb +1 -1
- data/tests/test_queue.rb +14 -0
- data/tests/test_resolver.rb +23 -0
- data/tests/test_set_sock_opt.rb +2 -0
- data/tests/test_ssl_dhparam.rb +83 -0
- data/tests/test_ssl_ecdh_curve.rb +79 -0
- data/tests/test_ssl_extensions.rb +49 -0
- data/tests/test_ssl_methods.rb +19 -0
- data/tests/test_ssl_protocols.rb +246 -0
- data/tests/test_ssl_verify.rb +44 -0
- data/tests/test_system.rb +4 -0
- data/tests/test_unbind_reason.rb +5 -1
- metadata +101 -20
- data/.gitignore +0 -21
- data/.travis.yml +0 -22
- data/.yardopts +0 -7
- data/Gemfile +0 -2
- data/Rakefile +0 -20
- data/eventmachine.gemspec +0 -38
- data/rakelib/cpp.rake_example +0 -77
data/lib/em/pool.rb
CHANGED
data/lib/em/pure_ruby.rb
CHANGED
@@ -66,6 +66,11 @@ module EventMachine
|
|
66
66
|
def release_machine
|
67
67
|
end
|
68
68
|
|
69
|
+
|
70
|
+
def stopping?
|
71
|
+
return Reactor.instance.stop_scheduled
|
72
|
+
end
|
73
|
+
|
69
74
|
# @private
|
70
75
|
def stop
|
71
76
|
Reactor.instance.stop
|
@@ -273,7 +278,7 @@ module EventMachine
|
|
273
278
|
|
274
279
|
HeartbeatInterval = 2
|
275
280
|
|
276
|
-
attr_reader :current_loop_time
|
281
|
+
attr_reader :current_loop_time, :stop_scheduled
|
277
282
|
|
278
283
|
def initialize
|
279
284
|
initialize_for_run
|
data/lib/em/queue.rb
CHANGED
@@ -17,7 +17,8 @@ module EventMachine
|
|
17
17
|
#
|
18
18
|
class Queue
|
19
19
|
def initialize
|
20
|
-
@
|
20
|
+
@sink = []
|
21
|
+
@drain = []
|
21
22
|
@popq = []
|
22
23
|
end
|
23
24
|
|
@@ -29,10 +30,14 @@ module EventMachine
|
|
29
30
|
def pop(*a, &b)
|
30
31
|
cb = EM::Callback(*a, &b)
|
31
32
|
EM.schedule do
|
32
|
-
if @
|
33
|
+
if @drain.empty?
|
34
|
+
@drain = @sink
|
35
|
+
@sink = []
|
36
|
+
end
|
37
|
+
if @drain.empty?
|
33
38
|
@popq << cb
|
34
39
|
else
|
35
|
-
cb.call @
|
40
|
+
cb.call @drain.shift
|
36
41
|
end
|
37
42
|
end
|
38
43
|
nil # Always returns nil
|
@@ -43,8 +48,12 @@ module EventMachine
|
|
43
48
|
# next reactor tick.
|
44
49
|
def push(*items)
|
45
50
|
EM.schedule do
|
46
|
-
@
|
47
|
-
|
51
|
+
@sink.push(*items)
|
52
|
+
unless @popq.empty?
|
53
|
+
@drain = @sink
|
54
|
+
@sink = []
|
55
|
+
@popq.shift.call @drain.shift until @drain.empty? || @popq.empty?
|
56
|
+
end
|
48
57
|
end
|
49
58
|
end
|
50
59
|
alias :<< :push
|
@@ -52,13 +61,13 @@ module EventMachine
|
|
52
61
|
# @return [Boolean]
|
53
62
|
# @note This is a peek, it's not thread safe, and may only tend toward accuracy.
|
54
63
|
def empty?
|
55
|
-
@
|
64
|
+
@drain.empty? && @sink.empty?
|
56
65
|
end
|
57
66
|
|
58
67
|
# @return [Integer] Queue size
|
59
68
|
# @note This is a peek, it's not thread safe, and may only tend toward accuracy.
|
60
69
|
def size
|
61
|
-
@
|
70
|
+
@drain.size + @sink.size
|
62
71
|
end
|
63
72
|
|
64
73
|
# @return [Integer] Waiting size
|
data/lib/em/resolver.rb
CHANGED
@@ -2,30 +2,31 @@ module EventMachine
|
|
2
2
|
module DNS
|
3
3
|
class Resolver
|
4
4
|
|
5
|
+
def self.windows?
|
6
|
+
if RUBY_PLATFORM =~ /mswin32|cygwin|mingw|bccwin/
|
7
|
+
require 'win32/resolv'
|
8
|
+
true
|
9
|
+
else
|
10
|
+
false
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
HOSTS_FILE = windows? ? Win32::Resolv.get_hosts_path : '/etc/hosts'
|
15
|
+
|
16
|
+
@hosts = nil
|
17
|
+
@nameservers = nil
|
18
|
+
@socket = nil
|
19
|
+
|
5
20
|
def self.resolve(hostname)
|
6
21
|
Request.new(socket, hostname)
|
7
22
|
end
|
8
23
|
|
9
|
-
@socket = @nameservers = nil
|
10
|
-
|
11
24
|
def self.socket
|
12
|
-
if
|
25
|
+
if @socket && @socket.error?
|
13
26
|
@socket = Socket.open
|
14
|
-
|
15
|
-
@
|
16
|
-
IO.readlines('/etc/hosts').each do |line|
|
17
|
-
next if line =~ /^#/
|
18
|
-
addr, host = line.split(/\s+/)
|
19
|
-
|
20
|
-
if @hosts[host]
|
21
|
-
@hosts[host] << addr
|
22
|
-
else
|
23
|
-
@hosts[host] = [addr]
|
24
|
-
end
|
25
|
-
end
|
27
|
+
else
|
28
|
+
@socket ||= Socket.open
|
26
29
|
end
|
27
|
-
|
28
|
-
@socket
|
29
30
|
end
|
30
31
|
|
31
32
|
def self.nameservers=(ns)
|
@@ -33,15 +34,23 @@ module EventMachine
|
|
33
34
|
end
|
34
35
|
|
35
36
|
def self.nameservers
|
36
|
-
if
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
return @nameservers if @nameservers
|
38
|
+
|
39
|
+
if windows?
|
40
|
+
_, ns = Win32::Resolv.get_resolv_info
|
41
|
+
return @nameservers = ns || []
|
42
|
+
end
|
43
|
+
|
44
|
+
@nameservers = []
|
45
|
+
IO.readlines('/etc/resolv.conf').each do |line|
|
46
|
+
if line =~ /^nameserver (.+)$/
|
47
|
+
@nameservers << $1.split(/\s+/).first
|
42
48
|
end
|
43
49
|
end
|
50
|
+
|
44
51
|
@nameservers
|
52
|
+
rescue
|
53
|
+
@nameservers = []
|
45
54
|
end
|
46
55
|
|
47
56
|
def self.nameserver
|
@@ -49,7 +58,21 @@ module EventMachine
|
|
49
58
|
end
|
50
59
|
|
51
60
|
def self.hosts
|
61
|
+
return @hosts if @hosts
|
62
|
+
|
63
|
+
@hosts = {}
|
64
|
+
IO.readlines(HOSTS_FILE).each do |line|
|
65
|
+
next if line =~ /^#/
|
66
|
+
addr, host = line.split(/\s+/)
|
67
|
+
|
68
|
+
next unless addr && host
|
69
|
+
@hosts[host] ||= []
|
70
|
+
@hosts[host] << addr
|
71
|
+
end
|
72
|
+
|
52
73
|
@hosts
|
74
|
+
rescue
|
75
|
+
@hosts = {}
|
53
76
|
end
|
54
77
|
end
|
55
78
|
|
data/lib/em/threaded_resource.rb
CHANGED
data/lib/em/version.rb
CHANGED
data/lib/eventmachine.rb
CHANGED
@@ -161,6 +161,7 @@ module EventMachine
|
|
161
161
|
# Clean up reactor state so a new reactor boots up in this child.
|
162
162
|
stop_event_loop
|
163
163
|
release_machine
|
164
|
+
cleanup_machine
|
164
165
|
@reactor_running = false
|
165
166
|
end
|
166
167
|
|
@@ -198,30 +199,8 @@ module EventMachine
|
|
198
199
|
@tails.pop.call
|
199
200
|
end
|
200
201
|
|
201
|
-
|
202
|
-
|
203
|
-
ensure
|
204
|
-
if @threadpool
|
205
|
-
@threadpool.each { |t| t.exit }
|
206
|
-
@threadpool.each do |t|
|
207
|
-
next unless t.alive?
|
208
|
-
begin
|
209
|
-
# Thread#kill! does not exist on 1.9 or rbx, and raises
|
210
|
-
# NotImplemented on jruby
|
211
|
-
t.kill!
|
212
|
-
rescue NoMethodError, NotImplementedError
|
213
|
-
t.kill
|
214
|
-
# XXX t.join here?
|
215
|
-
end
|
216
|
-
end
|
217
|
-
@threadqueue = nil
|
218
|
-
@resultqueue = nil
|
219
|
-
@threadpool = nil
|
220
|
-
@all_threads_spawned = false
|
221
|
-
end
|
222
|
-
|
223
|
-
@next_tick_queue = []
|
224
|
-
end
|
202
|
+
release_machine
|
203
|
+
cleanup_machine
|
225
204
|
@reactor_running = false
|
226
205
|
@reactor_thread = nil
|
227
206
|
end
|
@@ -266,13 +245,30 @@ module EventMachine
|
|
266
245
|
# Original patch by Aman Gupta.
|
267
246
|
#
|
268
247
|
Kernel.fork do
|
269
|
-
if
|
270
|
-
|
271
|
-
|
248
|
+
if reactor_running?
|
249
|
+
stop_event_loop
|
250
|
+
release_machine
|
251
|
+
cleanup_machine
|
272
252
|
@reactor_running = false
|
253
|
+
@reactor_thread = nil
|
273
254
|
end
|
274
|
-
|
255
|
+
run block
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
# Clean up Ruby space following a release_machine
|
260
|
+
def self.cleanup_machine
|
261
|
+
if @threadpool && !@threadpool.empty?
|
262
|
+
# Tell the threads to stop
|
263
|
+
@threadpool.each { |t| t.exit }
|
264
|
+
# Join the threads or bump the stragglers one more time
|
265
|
+
@threadpool.each { |t| t.join 0.01 || t.exit }
|
275
266
|
end
|
267
|
+
@threadpool = nil
|
268
|
+
@threadqueue = nil
|
269
|
+
@resultqueue = nil
|
270
|
+
@all_threads_spawned = false
|
271
|
+
@next_tick_queue = []
|
276
272
|
end
|
277
273
|
|
278
274
|
# Adds a block to call as the reactor is shutting down.
|
@@ -997,11 +993,14 @@ module EventMachine
|
|
997
993
|
# EventMachine.defer is used for integrating blocking operations into EventMachine's control flow.
|
998
994
|
# The action of {.defer} is to take the block specified in the first parameter (the "operation")
|
999
995
|
# and schedule it for asynchronous execution on an internal thread pool maintained by EventMachine.
|
1000
|
-
# When the operation completes, it will pass the result computed by the block (if any)
|
1001
|
-
#
|
1002
|
-
#
|
1003
|
-
#
|
1004
|
-
#
|
996
|
+
# When the operation completes, it will pass the result computed by the block (if any) back to the
|
997
|
+
# EventMachine reactor. Then, EventMachine calls the block specified in the second parameter to
|
998
|
+
# {.defer} (the "callback"), as part of its normal event handling loop. The result computed by the
|
999
|
+
# operation block is passed as a parameter to the callback. You may omit the callback parameter if
|
1000
|
+
# you don't need to execute any code after the operation completes. If the operation raises an
|
1001
|
+
# unhandled exception, the exception will be passed to the third parameter to {.defer} (the
|
1002
|
+
# "errback"), as part of its normal event handling loop. If no errback is provided, the exception
|
1003
|
+
# will be allowed to blow through to the main thread immediately.
|
1005
1004
|
#
|
1006
1005
|
# ## Caveats ##
|
1007
1006
|
#
|
@@ -1015,6 +1014,11 @@ module EventMachine
|
|
1015
1014
|
# the number of threads in its pool, so if you do this enough times, your subsequent deferred
|
1016
1015
|
# operations won't get a chance to run.
|
1017
1016
|
#
|
1017
|
+
# The threads within the EventMachine's thread pool have abort_on_exception set to true. As a result,
|
1018
|
+
# if an unhandled exception is raised by the deferred operation and an errback is not provided, it
|
1019
|
+
# will blow through to the main thread immediately. If the main thread is within an indiscriminate
|
1020
|
+
# rescue block at that time, the exception could be handled improperly by the main thread.
|
1021
|
+
#
|
1018
1022
|
# @example
|
1019
1023
|
#
|
1020
1024
|
# operation = proc {
|
@@ -1024,14 +1028,18 @@ module EventMachine
|
|
1024
1028
|
# callback = proc {|result|
|
1025
1029
|
# # do something with result here, such as send it back to a network client.
|
1026
1030
|
# }
|
1031
|
+
# errback = proc {|error|
|
1032
|
+
# # do something with error here, such as re-raising or logging.
|
1033
|
+
# }
|
1027
1034
|
#
|
1028
|
-
# EventMachine.defer(operation, callback)
|
1035
|
+
# EventMachine.defer(operation, callback, errback)
|
1029
1036
|
#
|
1030
1037
|
# @param [#call] op An operation you want to offload to EventMachine thread pool
|
1031
1038
|
# @param [#call] callback A callback that will be run on the event loop thread after `operation` finishes.
|
1039
|
+
# @param [#call] errback An errback that will be run on the event loop thread after `operation` raises an exception.
|
1032
1040
|
#
|
1033
1041
|
# @see EventMachine.threadpool_size
|
1034
|
-
def self.defer op = nil, callback = nil, &blk
|
1042
|
+
def self.defer op = nil, callback = nil, errback = nil, &blk
|
1035
1043
|
# OBSERVE that #next_tick hacks into this mechanism, so don't make any changes here
|
1036
1044
|
# without syncing there.
|
1037
1045
|
#
|
@@ -1048,7 +1056,7 @@ module EventMachine
|
|
1048
1056
|
spawn_threadpool
|
1049
1057
|
end
|
1050
1058
|
|
1051
|
-
@threadqueue << [op||blk,callback]
|
1059
|
+
@threadqueue << [op||blk,callback,errback]
|
1052
1060
|
end
|
1053
1061
|
|
1054
1062
|
|
@@ -1059,13 +1067,18 @@ module EventMachine
|
|
1059
1067
|
Thread.current.abort_on_exception = true
|
1060
1068
|
while true
|
1061
1069
|
begin
|
1062
|
-
op, cback = *@threadqueue.pop
|
1070
|
+
op, cback, eback = *@threadqueue.pop
|
1063
1071
|
rescue ThreadError
|
1064
1072
|
$stderr.puts $!.message
|
1065
1073
|
break # Ruby 2.0 may fail at Queue.pop
|
1066
1074
|
end
|
1067
|
-
|
1068
|
-
|
1075
|
+
begin
|
1076
|
+
result = op.call
|
1077
|
+
@resultqueue << [result, cback]
|
1078
|
+
rescue Exception => error
|
1079
|
+
raise error unless eback
|
1080
|
+
@resultqueue << [error, eback]
|
1081
|
+
end
|
1069
1082
|
EventMachine.signal_loopbreak
|
1070
1083
|
end
|
1071
1084
|
end
|
@@ -1477,9 +1490,13 @@ module EventMachine
|
|
1477
1490
|
rescue Errno::EBADF, IOError
|
1478
1491
|
end
|
1479
1492
|
end
|
1480
|
-
rescue
|
1481
|
-
|
1482
|
-
|
1493
|
+
rescue Exception => e
|
1494
|
+
if stopping?
|
1495
|
+
@wrapped_exception = $!
|
1496
|
+
stop
|
1497
|
+
else
|
1498
|
+
raise e
|
1499
|
+
end
|
1483
1500
|
end
|
1484
1501
|
elsif c = @acceptors.delete( conn_binding )
|
1485
1502
|
# no-op
|
Binary file
|
data/rakelib/package.rake
CHANGED
@@ -25,7 +25,7 @@ else
|
|
25
25
|
def setup_cross_compilation(ext)
|
26
26
|
unless RUBY_PLATFORM =~ /mswin|mingw/
|
27
27
|
ext.cross_compile = true
|
28
|
-
ext.cross_platform = ['x86-mingw32', '
|
28
|
+
ext.cross_platform = ['x86-mingw32', 'x64-mingw32']
|
29
29
|
end
|
30
30
|
end
|
31
31
|
def hack_cross_compilation(ext)
|
@@ -96,3 +96,25 @@ def gem_cmd(action, name, *args)
|
|
96
96
|
end
|
97
97
|
|
98
98
|
Rake::Task[:clean].enhance [:clobber_package]
|
99
|
+
|
100
|
+
# DevKit task following the example of Luis Lavena's test-ruby-c-extension
|
101
|
+
task :devkit do
|
102
|
+
begin
|
103
|
+
require "devkit"
|
104
|
+
rescue LoadError => e
|
105
|
+
abort "Failed to activate RubyInstaller's DevKit required for compilation."
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
if RUBY_PLATFORM =~ /mingw|mswin/
|
110
|
+
Rake::Task['compile'].prerequisites.unshift 'devkit'
|
111
|
+
end
|
112
|
+
|
113
|
+
desc "Build binary gems for Windows with rake-compiler-dock"
|
114
|
+
task 'gem:windows' do
|
115
|
+
require 'rake_compiler_dock'
|
116
|
+
RakeCompilerDock.sh <<-EOT
|
117
|
+
RUBY_CC_VERSION="${RUBY_CC_VERSION//1.8.7/}"
|
118
|
+
bundle && rake cross native gem
|
119
|
+
EOT
|
120
|
+
end
|
data/tests/dhparam.pem
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
-----BEGIN DH PARAMETERS-----
|
2
|
+
MIICCAKCAgEAikiatXa5aAteOtd6hOO33npjCvJByD3dwuM8rWzz0DFZdUH9nFJi
|
3
|
+
b0VvTVweVECb6XZBsrDNLqGQykCrm43swSk5D9XQCGJLxFERD6yk3b90xaeCm3/a
|
4
|
+
b0Ek5ZVvV73Cc/YbVmpBiOHoTFpUFJLZ7pLMQUSn8y3qUlNcY9/88HuwFi1s1lRM
|
5
|
+
ovihSRyZMYAuYWOD4yuOuIcroKVjD6gWFrsW9XrALWny6vUXQrhk8Q3rj+wM6ZtE
|
6
|
+
5afcB0b6ZJtphrDfk3dFjOVG/zVT37VWgrY8GABrpo2ey0W0WIQJ7rDKLaPaI4kc
|
7
|
+
voOgC2K8Z3kSARZK+jULnwmBeYECz4EH/FF6FEp3GOKtkL4mqEkvh1n5EAesDOGl
|
8
|
+
iiX+RZXcUrZliSeifSXBTMJWWFVC0fkGIMb9PTZfZHyAC54lpuxzVki0HIyQG9Fs
|
9
|
+
41zBJ5e8eEoXXlfUYtduUC35YGy2IxSzYLAJE76rctAZSWghha9xLOCDFoLjMr8h
|
10
|
+
FosKeHKJcBQ0bc8ymOpRIfrYLWhc0Pz2zkpJ/4eYw9t7NYg7S+jP19IE0gUnuM9v
|
11
|
+
SpoYMtS28tP9nEdokdwuBKD0D3bJEBBefDlHgfXoMgvy9Hivc9PBGGNTNpyFPpwF
|
12
|
+
sWVAkfhoNMJMC5V7LZsze+lftiDtzVoLSPDa9bO4BK7b/MgwCxfOhGsCAQI=
|
13
|
+
-----END DH PARAMETERS-----
|
data/tests/em_test_helper.rb
CHANGED
@@ -31,6 +31,61 @@ class Test::Unit::TestCase
|
|
31
31
|
@@port
|
32
32
|
end
|
33
33
|
|
34
|
+
# Returns true if the host have a localhost 127.0.0.1 IPv4.
|
35
|
+
def self.local_ipv4?
|
36
|
+
return @@has_local_ipv4 if defined?(@@has_local_ipv4)
|
37
|
+
begin
|
38
|
+
get_my_ipv4_address "127.0.0.1"
|
39
|
+
@@has_local_ipv4 = true
|
40
|
+
rescue
|
41
|
+
@@has_local_ipv4 = false
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns true if the host have a public IPv4 and stores it in
|
46
|
+
# @@public_ipv4.
|
47
|
+
def self.public_ipv4?
|
48
|
+
return @@has_public_ipv4 if defined?(@@has_public_ipv4)
|
49
|
+
begin
|
50
|
+
@@public_ipv4 = get_my_ipv4_address "1.2.3.4"
|
51
|
+
@@has_public_ipv4 = true
|
52
|
+
rescue
|
53
|
+
@@has_public_ipv4 = false
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Returns true if the host have a localhost ::1 IPv6.
|
58
|
+
def self.local_ipv6?
|
59
|
+
return @@has_local_ipv6 if defined?(@@has_local_ipv6)
|
60
|
+
begin
|
61
|
+
get_my_ipv6_address "::1"
|
62
|
+
@@has_local_ipv6 = true
|
63
|
+
rescue
|
64
|
+
@@has_local_ipv6 = false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns true if the host have a public IPv6 and stores it in
|
69
|
+
# @@public_ipv6.
|
70
|
+
def self.public_ipv6?
|
71
|
+
return @@has_public_ipv6 if defined?(@@has_public_ipv6)
|
72
|
+
begin
|
73
|
+
@@public_ipv6 = get_my_ipv6_address "2001::1"
|
74
|
+
@@has_public_ipv6 = true
|
75
|
+
rescue
|
76
|
+
@@has_public_ipv6 = false
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Returns an array with the localhost addresses (IPv4 and/or IPv6).
|
81
|
+
def local_ips
|
82
|
+
return @@local_ips if defined?(@@local_ips)
|
83
|
+
@@local_ips = []
|
84
|
+
@@local_ips << "127.0.0.1" if self.class.local_ipv4?
|
85
|
+
@@local_ips << "::1" if self.class.local_ipv6?
|
86
|
+
@@local_ips
|
87
|
+
end
|
88
|
+
|
34
89
|
def exception_class
|
35
90
|
jruby? ? NativeException : RuntimeError
|
36
91
|
end
|
@@ -69,4 +124,28 @@ class Test::Unit::TestCase
|
|
69
124
|
$VERBOSE = backup
|
70
125
|
end
|
71
126
|
end
|
127
|
+
|
128
|
+
|
129
|
+
private
|
130
|
+
|
131
|
+
def self.get_my_ipv4_address ip
|
132
|
+
orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true # turn off reverse DNS resolution temporarily
|
133
|
+
UDPSocket.open(Socket::AF_INET) do |s|
|
134
|
+
s.connect ip, 1
|
135
|
+
s.addr.last
|
136
|
+
end
|
137
|
+
ensure
|
138
|
+
Socket.do_not_reverse_lookup = orig
|
139
|
+
end
|
140
|
+
|
141
|
+
def self.get_my_ipv6_address ip
|
142
|
+
orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true # turn off reverse DNS resolution temporarily
|
143
|
+
UDPSocket.open(Socket::AF_INET6) do |s|
|
144
|
+
s.connect ip, 1
|
145
|
+
s.addr.last
|
146
|
+
end
|
147
|
+
ensure
|
148
|
+
Socket.do_not_reverse_lookup = orig
|
149
|
+
end
|
150
|
+
|
72
151
|
end
|