drab 0.1.0

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.
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: false
2
+ module DRab
3
+ class DRabObject # :nodoc:
4
+ def ==(other)
5
+ return false unless DRabObject === other
6
+ (@ref == other.__drabref) && (@uri == other.__draburi)
7
+ end
8
+
9
+ def hash
10
+ [@uri, @ref].hash
11
+ end
12
+
13
+ alias eql? ==
14
+ end
15
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: false
2
+ =begin
3
+ external service
4
+ Copyright (c) 2000,2002 Masatoshi SEKI
5
+ =end
6
+
7
+ require 'drab/drab'
8
+ require 'monitor'
9
+
10
+ module DRab
11
+ class ExtServ
12
+ include MonitorMixin
13
+ include DRabUndumped
14
+
15
+ def initialize(there, name, server=nil)
16
+ super()
17
+ @server = server || DRab::primary_server
18
+ @name = name
19
+ ro = DRabObject.new(nil, there)
20
+ synchronize do
21
+ @invoker = ro.regist(name, DRabObject.new(self, @server.uri))
22
+ end
23
+ end
24
+ attr_reader :server
25
+
26
+ def front
27
+ DRabObject.new(nil, @server.uri)
28
+ end
29
+
30
+ def stop_service
31
+ synchronize do
32
+ @invoker.unregist(@name)
33
+ server = @server
34
+ @server = nil
35
+ server.stop_service
36
+ true
37
+ end
38
+ end
39
+
40
+ def alive?
41
+ @server ? @server.alive? : false
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: false
2
+ =begin
3
+ external service manager
4
+ Copyright (c) 2000 Masatoshi SEKI
5
+ =end
6
+
7
+ require 'drab/drab'
8
+ require 'thread'
9
+ require 'monitor'
10
+
11
+ module DRab
12
+ class ExtServManager
13
+ include DRabUndumped
14
+ include MonitorMixin
15
+
16
+ @@command = {}
17
+
18
+ def self.command
19
+ @@command
20
+ end
21
+
22
+ def self.command=(cmd)
23
+ @@command = cmd
24
+ end
25
+
26
+ def initialize
27
+ super()
28
+ @cond = new_cond
29
+ @servers = {}
30
+ @waiting = []
31
+ @queue = Thread::Queue.new
32
+ @thread = invoke_thread
33
+ @uri = nil
34
+ end
35
+ attr_accessor :uri
36
+
37
+ def service(name)
38
+ synchronize do
39
+ while true
40
+ server = @servers[name]
41
+ return server if server&.alive?
42
+ invoke_service(name)
43
+ @cond.wait
44
+ end
45
+ end
46
+ end
47
+
48
+ def regist(name, ro)
49
+ synchronize do
50
+ @servers[name] = ro
51
+ @cond.signal
52
+ end
53
+ self
54
+ end
55
+
56
+ def unregist(name)
57
+ synchronize do
58
+ @servers.delete(name)
59
+ end
60
+ end
61
+
62
+ private
63
+ def invoke_thread
64
+ Thread.new do
65
+ while true
66
+ name = @queue.pop
67
+ invoke_service_command(name, @@command[name])
68
+ end
69
+ end
70
+ end
71
+
72
+ def invoke_service(name)
73
+ @queue.push(name)
74
+ end
75
+
76
+ def invoke_service_command(name, command)
77
+ raise "invalid command. name: #{name}" unless command
78
+ synchronize do
79
+ return if @servers.include?(name)
80
+ @servers[name] = false
81
+ end
82
+ uri = @uri || DRab.uri
83
+ if command.respond_to? :to_ary
84
+ command = command.to_ary + [uri, name]
85
+ pid = spawn(*command)
86
+ else
87
+ pid = spawn("#{command} #{uri} #{name}")
88
+ end
89
+ th = Process.detach(pid)
90
+ th[:drab_service] = name
91
+ th
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,165 @@
1
+ # frozen_string_literal: false
2
+ require 'drab/drab'
3
+ require 'monitor'
4
+
5
+ module DRab
6
+
7
+ # Gateway id conversion forms a gateway between different DRab protocols or
8
+ # networks.
9
+ #
10
+ # The gateway needs to install this id conversion and create servers for
11
+ # each of the protocols or networks it will be a gateway between. It then
12
+ # needs to create a server that attaches to each of these networks. For
13
+ # example:
14
+ #
15
+ # require 'drab'
16
+ # require 'unix'
17
+ # require 'drab/gw'
18
+ #
19
+ # DRab.install_id_conv DRab::GWIdConv.new
20
+ # gw = DRab::GW.new
21
+ # s1 = DRab::DRabServer.new 'drabunix:/path/to/gateway', gw
22
+ # s2 = DRab::DRabServer.new 'druby://example:10000', gw
23
+ #
24
+ # s1.thread.join
25
+ # s2.thread.join
26
+ #
27
+ # Each client must register services with the gateway, for example:
28
+ #
29
+ # DRab.start_service 'drabunix:', nil # an anonymous server
30
+ # gw = DRabObject.new nil, 'drabunix:/path/to/gateway'
31
+ # gw[:unix] = some_service
32
+ # DRab.thread.join
33
+
34
+ class GWIdConv < DRabIdConv
35
+ def to_obj(ref) # :nodoc:
36
+ if Array === ref && ref[0] == :DRabObject
37
+ return DRabObject.new_with(ref[1], ref[2])
38
+ end
39
+ super(ref)
40
+ end
41
+ end
42
+
43
+ # The GW provides a synchronized store for participants in the gateway to
44
+ # communicate.
45
+
46
+ class GW
47
+ include MonitorMixin
48
+
49
+ # Creates a new GW
50
+
51
+ def initialize
52
+ super()
53
+ @hash = {}
54
+ end
55
+
56
+ # Retrieves +key+ from the GW
57
+
58
+ def [](key)
59
+ synchronize do
60
+ @hash[key]
61
+ end
62
+ end
63
+
64
+ # Stores value +v+ at +key+ in the GW
65
+
66
+ def []=(key, v)
67
+ synchronize do
68
+ @hash[key] = v
69
+ end
70
+ end
71
+ end
72
+
73
+ class DRabObject # :nodoc:
74
+ def self._load(s)
75
+ #uri, ref = Marshal::load(s)
76
+ uri, ref = JSON::load(s)
77
+ if DRab.uri == uri
78
+ return ref ? DRab.to_obj(ref) : DRab.front
79
+ end
80
+
81
+ self.new_with(DRab.uri, [:DRabObject, uri, ref])
82
+ end
83
+
84
+ def _dump(lv)
85
+ if DRab.uri == @uri
86
+ if Array === @ref && @ref[0] == :DRabObject
87
+ #Marshal::dump([@ref[1], @ref[2]])
88
+ JSON::dump([@ref[1], @ref[2]])
89
+ else
90
+ #Marshal::dump([@uri, @ref]) # ??
91
+ JSON::dump([@uri, @ref]) # ??
92
+ end
93
+ else
94
+ #Marshal::dump([DRab.uri, [:DRabObject, @uri, @ref]])
95
+ JSON::dump([DRab.uri, [:DRabObject, @uri, @ref]])
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ =begin
102
+ DRab.install_id_conv(DRab::GWIdConv.new)
103
+
104
+ front = DRab::GW.new
105
+
106
+ s1 = DRab::DRabServer.new('drabunix:/tmp/gw_b_a', front)
107
+ s2 = DRab::DRabServer.new('drabunix:/tmp/gw_b_c', front)
108
+
109
+ s1.thread.join
110
+ s2.thread.join
111
+ =end
112
+
113
+ =begin
114
+ # foo.rb
115
+
116
+ require 'drab/drab'
117
+
118
+ class Foo
119
+ include DRabUndumped
120
+ def initialize(name, peer=nil)
121
+ @name = name
122
+ @peer = peer
123
+ end
124
+
125
+ def ping(obj)
126
+ puts "#{@name}: ping: #{obj.inspect}"
127
+ @peer.ping(self) if @peer
128
+ end
129
+ end
130
+ =end
131
+
132
+ =begin
133
+ # gw_a.rb
134
+ require 'drab/unix'
135
+ require 'foo'
136
+
137
+ obj = Foo.new('a')
138
+ DRab.start_service("drabunix:/tmp/gw_a", obj)
139
+
140
+ robj = DRabObject.new_with_uri('drabunix:/tmp/gw_b_a')
141
+ robj[:a] = obj
142
+
143
+ DRab.thread.join
144
+ =end
145
+
146
+ =begin
147
+ # gw_c.rb
148
+ require 'drab/unix'
149
+ require 'foo'
150
+
151
+ foo = Foo.new('c', nil)
152
+
153
+ DRab.start_service("drabunix:/tmp/gw_c", nil)
154
+
155
+ robj = DRabObject.new_with_uri("drabunix:/tmp/gw_b_c")
156
+
157
+ puts "c->b"
158
+ a = robj[:a]
159
+ sleep 2
160
+
161
+ a.ping(foo)
162
+
163
+ DRab.thread.join
164
+ =end
165
+
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: false
2
+ # for ruby-1.8.0
3
+
4
+ module DRab # :nodoc: all
5
+ class DRabServer
6
+ module InvokeMethod18Mixin
7
+ def block_yield(x)
8
+ if x.size == 1 && x[0].class == Array
9
+ x[0] = DRabArray.new(x[0])
10
+ end
11
+ @block.call(*x)
12
+ end
13
+
14
+ def perform_with_block
15
+ @obj.__send__(@msg_id, *@argv) do |*x|
16
+ jump_error = nil
17
+ begin
18
+ block_value = block_yield(x)
19
+ rescue LocalJumpError
20
+ jump_error = $!
21
+ end
22
+ if jump_error
23
+ case jump_error.reason
24
+ when :break
25
+ break(jump_error.exit_value)
26
+ else
27
+ raise jump_error
28
+ end
29
+ end
30
+ block_value
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: false
2
+ require 'observer'
3
+
4
+ module DRab
5
+ # The Observable module extended to DRab. See Observable for details.
6
+ module DRabObservable
7
+ include Observable
8
+
9
+ # Notifies observers of a change in state. See also
10
+ # Observable#notify_observers
11
+ def notify_observers(*arg)
12
+ if defined? @observer_state and @observer_state
13
+ if defined? @observer_peers
14
+ @observer_peers.each do |observer, method|
15
+ begin
16
+ observer.send(method, *arg)
17
+ rescue
18
+ delete_observer(observer)
19
+ end
20
+ end
21
+ end
22
+ @observer_state = false
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,346 @@
1
+ # frozen_string_literal: false
2
+ require 'socket'
3
+ require 'openssl'
4
+ require 'drab/drab'
5
+ require 'singleton'
6
+
7
+ module DRab
8
+
9
+ # The protocol for DRab over an SSL socket
10
+ #
11
+ # The URI for a DRab socket over SSL is:
12
+ # <code>drabssl://<host>:<port>?<option></code>. The option is optional
13
+ class DRabSSLSocket < DRabTCPSocket
14
+
15
+ # SSLConfig handles the needed SSL information for establishing a
16
+ # DRabSSLSocket connection, including generating the X509 / RSA pair.
17
+ #
18
+ # An instance of this config can be passed to DRabSSLSocket.new,
19
+ # DRabSSLSocket.open and DRabSSLSocket.open_server
20
+ #
21
+ # See DRab::DRabSSLSocket::SSLConfig.new for more details
22
+ class SSLConfig
23
+
24
+ # Default values for a SSLConfig instance.
25
+ #
26
+ # See DRab::DRabSSLSocket::SSLConfig.new for more details
27
+ DEFAULT = {
28
+ :SSLCertificate => nil,
29
+ :SSLPrivateKey => nil,
30
+ :SSLClientCA => nil,
31
+ :SSLCACertificatePath => nil,
32
+ :SSLCACertificateFile => nil,
33
+ :SSLTmpDhCallback => nil,
34
+ :SSLVerifyMode => ::OpenSSL::SSL::VERIFY_NONE,
35
+ :SSLVerifyDepth => nil,
36
+ :SSLVerifyCallback => nil, # custom verification
37
+ :SSLCertificateStore => nil,
38
+ # Must specify if you use auto generated certificate.
39
+ :SSLCertName => nil, # e.g. [["CN","fqdn.example.com"]]
40
+ :SSLCertComment => "Generated by Ruby/OpenSSL"
41
+ }
42
+
43
+ # Create a new DRab::DRabSSLSocket::SSLConfig instance
44
+ #
45
+ # The DRab::DRabSSLSocket will take either a +config+ Hash or an instance
46
+ # of SSLConfig, and will setup the certificate for its session for the
47
+ # configuration. If want it to generate a generic certificate, the bare
48
+ # minimum is to provide the :SSLCertName
49
+ #
50
+ # === Config options
51
+ #
52
+ # From +config+ Hash:
53
+ #
54
+ # :SSLCertificate ::
55
+ # An instance of OpenSSL::X509::Certificate. If this is not provided,
56
+ # then a generic X509 is generated, with a correspond :SSLPrivateKey
57
+ #
58
+ # :SSLPrivateKey ::
59
+ # A private key instance, like OpenSSL::PKey::RSA. This key must be
60
+ # the key that signed the :SSLCertificate
61
+ #
62
+ # :SSLClientCA ::
63
+ # An OpenSSL::X509::Certificate, or Array of certificates that will
64
+ # used as ClientCAs in the SSL Context
65
+ #
66
+ # :SSLCACertificatePath ::
67
+ # A path to the directory of CA certificates. The certificates must
68
+ # be in PEM format.
69
+ #
70
+ # :SSLCACertificateFile ::
71
+ # A path to a CA certificate file, in PEM format.
72
+ #
73
+ # :SSLTmpDhCallback ::
74
+ # A DH callback. See OpenSSL::SSL::SSLContext.tmp_dh_callback
75
+ #
76
+ # :SSLVerifyMode ::
77
+ # This is the SSL verification mode. See OpenSSL::SSL::VERIFY_* for
78
+ # available modes. The default is OpenSSL::SSL::VERIFY_NONE
79
+ #
80
+ # :SSLVerifyDepth ::
81
+ # Number of CA certificates to walk, when verifying a certificate
82
+ # chain.
83
+ #
84
+ # :SSLVerifyCallback ::
85
+ # A callback to be used for additional verification. See
86
+ # OpenSSL::SSL::SSLContext.verify_callback
87
+ #
88
+ # :SSLCertificateStore ::
89
+ # A OpenSSL::X509::Store used for verification of certificates
90
+ #
91
+ # :SSLCertName ::
92
+ # Issuer name for the certificate. This is required when generating
93
+ # the certificate (if :SSLCertificate and :SSLPrivateKey were not
94
+ # given). The value of this is to be an Array of pairs:
95
+ #
96
+ # [["C", "Raleigh"], ["ST","North Carolina"],
97
+ # ["CN","fqdn.example.com"]]
98
+ #
99
+ # See also OpenSSL::X509::Name
100
+ #
101
+ # :SSLCertComment ::
102
+ # A comment to be used for generating the certificate. The default is
103
+ # "Generated by Ruby/OpenSSL"
104
+ #
105
+ #
106
+ # === Example
107
+ #
108
+ # These values can be added after the fact, like a Hash.
109
+ #
110
+ # require 'ssl'
111
+ # c = DRab::DRabSSLSocket::SSLConfig.new {}
112
+ # c[:SSLCertificate] =
113
+ # OpenSSL::X509::Certificate.new(File.read('mycert.crt'))
114
+ # c[:SSLPrivateKey] = OpenSSL::PKey::RSA.new(File.read('mycert.key'))
115
+ # c[:SSLVerifyMode] = OpenSSL::SSL::VERIFY_PEER
116
+ # c[:SSLCACertificatePath] = "/etc/ssl/certs/"
117
+ # c.setup_certificate
118
+ #
119
+ # or
120
+ #
121
+ # require 'ssl'
122
+ # c = DRab::DRabSSLSocket::SSLConfig.new({
123
+ # :SSLCertName => [["CN" => DRab::DRabSSLSocket.getservername]]
124
+ # })
125
+ # c.setup_certificate
126
+ #
127
+ def initialize(config)
128
+ @config = config
129
+ @cert = config[:SSLCertificate]
130
+ @pkey = config[:SSLPrivateKey]
131
+ @ssl_ctx = nil
132
+ end
133
+
134
+ # A convenience method to access the values like a Hash
135
+ def [](key);
136
+ @config[key] || DEFAULT[key]
137
+ end
138
+
139
+ # Connect to IO +tcp+, with context of the current certificate
140
+ # configuration
141
+ def connect(tcp)
142
+ ssl = ::OpenSSL::SSL::SSLSocket.new(tcp, @ssl_ctx)
143
+ ssl.sync = true
144
+ ssl.connect
145
+ ssl
146
+ end
147
+
148
+ # Accept connection to IO +tcp+, with context of the current certificate
149
+ # configuration
150
+ def accept(tcp)
151
+ ssl = OpenSSL::SSL::SSLSocket.new(tcp, @ssl_ctx)
152
+ ssl.sync = true
153
+ ssl.accept
154
+ ssl
155
+ end
156
+
157
+ # Ensures that :SSLCertificate and :SSLPrivateKey have been provided
158
+ # or that a new certificate is generated with the other parameters
159
+ # provided.
160
+ def setup_certificate
161
+ if @cert && @pkey
162
+ return
163
+ end
164
+
165
+ rsa = OpenSSL::PKey::RSA.new(1024){|p, n|
166
+ next unless self[:verbose]
167
+ case p
168
+ when 0; $stderr.putc "." # BN_generate_prime
169
+ when 1; $stderr.putc "+" # BN_generate_prime
170
+ when 2; $stderr.putc "*" # searching good prime,
171
+ # n = #of try,
172
+ # but also data from BN_generate_prime
173
+ when 3; $stderr.putc "\n" # found good prime, n==0 - p, n==1 - q,
174
+ # but also data from BN_generate_prime
175
+ else; $stderr.putc "*" # BN_generate_prime
176
+ end
177
+ }
178
+
179
+ cert = OpenSSL::X509::Certificate.new
180
+ cert.version = 3
181
+ cert.serial = 0
182
+ name = OpenSSL::X509::Name.new(self[:SSLCertName])
183
+ cert.subject = name
184
+ cert.issuer = name
185
+ cert.not_before = Time.now
186
+ cert.not_after = Time.now + (365*24*60*60)
187
+ cert.public_key = rsa.public_key
188
+
189
+ ef = OpenSSL::X509::ExtensionFactory.new(nil,cert)
190
+ cert.extensions = [
191
+ ef.create_extension("basicConstraints","CA:FALSE"),
192
+ ef.create_extension("subjectKeyIdentifier", "hash") ]
193
+ ef.issuer_certificate = cert
194
+ cert.add_extension(ef.create_extension("authorityKeyIdentifier",
195
+ "keyid:always,issuer:always"))
196
+ if comment = self[:SSLCertComment]
197
+ cert.add_extension(ef.create_extension("nsComment", comment))
198
+ end
199
+ cert.sign(rsa, OpenSSL::Digest::SHA1.new)
200
+
201
+ @cert = cert
202
+ @pkey = rsa
203
+ end
204
+
205
+ # Establish the OpenSSL::SSL::SSLContext with the configuration
206
+ # parameters provided.
207
+ def setup_ssl_context
208
+ ctx = ::OpenSSL::SSL::SSLContext.new
209
+ ctx.cert = @cert
210
+ ctx.key = @pkey
211
+ ctx.client_ca = self[:SSLClientCA]
212
+ ctx.ca_path = self[:SSLCACertificatePath]
213
+ ctx.ca_file = self[:SSLCACertificateFile]
214
+ ctx.tmp_dh_callback = self[:SSLTmpDhCallback]
215
+ ctx.verify_mode = self[:SSLVerifyMode]
216
+ ctx.verify_depth = self[:SSLVerifyDepth]
217
+ ctx.verify_callback = self[:SSLVerifyCallback]
218
+ ctx.cert_store = self[:SSLCertificateStore]
219
+ @ssl_ctx = ctx
220
+ end
221
+ end
222
+
223
+ # Parse the dRuby +uri+ for an SSL connection.
224
+ #
225
+ # Expects drabssl://...
226
+ #
227
+ # Raises DRabBadScheme or DRabBadURI if +uri+ is not matching or malformed
228
+ def self.parse_uri(uri) # :nodoc:
229
+ if uri =~ /^drabssl:\/\/(.*?):(\d+)(\?(.*))?$/
230
+ host = $1
231
+ port = $2.to_i
232
+ option = $4
233
+ [host, port, option]
234
+ else
235
+ raise(DRabBadScheme, uri) unless uri =~ /^drabssl:/
236
+ raise(DRabBadURI, 'can\'t parse uri:' + uri)
237
+ end
238
+ end
239
+
240
+ # Return an DRab::DRabSSLSocket instance as a client-side connection,
241
+ # with the SSL connected. This is called from DRab::start_service or while
242
+ # connecting to a remote object:
243
+ #
244
+ # DRab.start_service 'drabssl://localhost:0', front, config
245
+ #
246
+ # +uri+ is the URI we are connected to,
247
+ # <code>'drabssl://localhost:0'</code> above, +config+ is our
248
+ # configuration. Either a Hash or DRab::DRabSSLSocket::SSLConfig
249
+ def self.open(uri, config)
250
+ host, port, = parse_uri(uri)
251
+ host.untaint
252
+ port.untaint
253
+ soc = TCPSocket.open(host, port)
254
+ ssl_conf = SSLConfig::new(config)
255
+ ssl_conf.setup_ssl_context
256
+ ssl = ssl_conf.connect(soc)
257
+ self.new(uri, ssl, ssl_conf, true)
258
+ end
259
+
260
+ # Returns a DRab::DRabSSLSocket instance as a server-side connection, with
261
+ # the SSL connected. This is called from DRab::start_service or while
262
+ # connecting to a remote object:
263
+ #
264
+ # DRab.start_service 'drabssl://localhost:0', front, config
265
+ #
266
+ # +uri+ is the URI we are connected to,
267
+ # <code>'drabssl://localhost:0'</code> above, +config+ is our
268
+ # configuration. Either a Hash or DRab::DRabSSLSocket::SSLConfig
269
+ def self.open_server(uri, config)
270
+ uri = 'drabssl://:0' unless uri
271
+ host, port, = parse_uri(uri)
272
+ if host.size == 0
273
+ host = getservername
274
+ soc = open_server_inaddr_any(host, port)
275
+ else
276
+ soc = TCPServer.open(host, port)
277
+ end
278
+ port = soc.addr[1] if port == 0
279
+ @uri = "drabssl://#{host}:#{port}"
280
+
281
+ ssl_conf = SSLConfig.new(config)
282
+ ssl_conf.setup_certificate
283
+ ssl_conf.setup_ssl_context
284
+ self.new(@uri, soc, ssl_conf, false)
285
+ end
286
+
287
+ # This is a convenience method to parse +uri+ and separate out any
288
+ # additional options appended in the +uri+.
289
+ #
290
+ # Returns an option-less uri and the option => [uri,option]
291
+ #
292
+ # The +config+ is completely unused, so passing nil is sufficient.
293
+ def self.uri_option(uri, config) # :nodoc:
294
+ host, port, option = parse_uri(uri)
295
+ return "drabssl://#{host}:#{port}", option
296
+ end
297
+
298
+ # Create a DRab::DRabSSLSocket instance.
299
+ #
300
+ # +uri+ is the URI we are connected to.
301
+ # +soc+ is the tcp socket we are bound to.
302
+ # +config+ is our configuration. Either a Hash or SSLConfig
303
+ # +is_established+ is a boolean of whether +soc+ is currently established
304
+ #
305
+ # This is called automatically based on the DRab protocol.
306
+ def initialize(uri, soc, config, is_established)
307
+ @ssl = is_established ? soc : nil
308
+ super(uri, soc.to_io, config)
309
+ end
310
+
311
+ # Returns the SSL stream
312
+ def stream; @ssl; end # :nodoc:
313
+
314
+ # Closes the SSL stream before closing the dRuby connection.
315
+ def close # :nodoc:
316
+ if @ssl
317
+ @ssl.close
318
+ @ssl = nil
319
+ end
320
+ super
321
+ end
322
+
323
+ def accept # :nodoc:
324
+ begin
325
+ while true
326
+ soc = accept_or_shutdown
327
+ return nil unless soc
328
+ break if (@acl ? @acl.allow_socket?(soc) : true)
329
+ soc.close
330
+ end
331
+ begin
332
+ ssl = @config.accept(soc)
333
+ rescue Exception
334
+ soc.close
335
+ raise
336
+ end
337
+ self.class.new(uri, ssl, @config, true)
338
+ rescue OpenSSL::SSL::SSLError
339
+ warn("#{__FILE__}:#{__LINE__}: warning: #{$!.message} (#{$!.class})") if @config[:verbose]
340
+ retry
341
+ end
342
+ end
343
+ end
344
+
345
+ DRabProtocol.add_protocol(DRabSSLSocket)
346
+ end