drb 2.0.4

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 DRb
3
+ class DRbObject # :nodoc:
4
+ def ==(other)
5
+ return false unless DRbObject === other
6
+ (@ref == other.__drbref) && (@uri == other.__drburi)
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_relative 'drb'
8
+ require 'monitor'
9
+
10
+ module DRb
11
+ class ExtServ
12
+ include MonitorMixin
13
+ include DRbUndumped
14
+
15
+ def initialize(there, name, server=nil)
16
+ super()
17
+ @server = server || DRb::primary_server
18
+ @name = name
19
+ ro = DRbObject.new(nil, there)
20
+ synchronize do
21
+ @invoker = ro.regist(name, DRbObject.new(self, @server.uri))
22
+ end
23
+ end
24
+ attr_reader :server
25
+
26
+ def front
27
+ DRbObject.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,92 @@
1
+ # frozen_string_literal: false
2
+ =begin
3
+ external service manager
4
+ Copyright (c) 2000 Masatoshi SEKI
5
+ =end
6
+
7
+ require_relative 'drb'
8
+ require 'monitor'
9
+
10
+ module DRb
11
+ class ExtServManager
12
+ include DRbUndumped
13
+ include MonitorMixin
14
+
15
+ @@command = {}
16
+
17
+ def self.command
18
+ @@command
19
+ end
20
+
21
+ def self.command=(cmd)
22
+ @@command = cmd
23
+ end
24
+
25
+ def initialize
26
+ super()
27
+ @cond = new_cond
28
+ @servers = {}
29
+ @waiting = []
30
+ @queue = Thread::Queue.new
31
+ @thread = invoke_thread
32
+ @uri = nil
33
+ end
34
+ attr_accessor :uri
35
+
36
+ def service(name)
37
+ synchronize do
38
+ while true
39
+ server = @servers[name]
40
+ return server if server && server.alive? # server may be `false'
41
+ invoke_service(name)
42
+ @cond.wait
43
+ end
44
+ end
45
+ end
46
+
47
+ def regist(name, ro)
48
+ synchronize do
49
+ @servers[name] = ro
50
+ @cond.signal
51
+ end
52
+ self
53
+ end
54
+
55
+ def unregist(name)
56
+ synchronize do
57
+ @servers.delete(name)
58
+ end
59
+ end
60
+
61
+ private
62
+ def invoke_thread
63
+ Thread.new do
64
+ while name = @queue.pop
65
+ invoke_service_command(name, @@command[name])
66
+ end
67
+ end
68
+ end
69
+
70
+ def invoke_service(name)
71
+ @queue.push(name)
72
+ end
73
+
74
+ def invoke_service_command(name, command)
75
+ raise "invalid command. name: #{name}" unless command
76
+ synchronize do
77
+ return if @servers.include?(name)
78
+ @servers[name] = false
79
+ end
80
+ uri = @uri || DRb.uri
81
+ if command.respond_to? :to_ary
82
+ command = command.to_ary + [uri, name]
83
+ pid = spawn(*command)
84
+ else
85
+ pid = spawn("#{command} #{uri} #{name}")
86
+ end
87
+ th = Process.detach(pid)
88
+ th[:drb_service] = name
89
+ th
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,161 @@
1
+ # frozen_string_literal: false
2
+ require_relative 'drb'
3
+ require 'monitor'
4
+
5
+ module DRb
6
+
7
+ # Gateway id conversion forms a gateway between different DRb 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 'drb/drb'
16
+ # require 'drb/unix'
17
+ # require 'drb/gw'
18
+ #
19
+ # DRb.install_id_conv DRb::GWIdConv.new
20
+ # gw = DRb::GW.new
21
+ # s1 = DRb::DRbServer.new 'drbunix:/path/to/gateway', gw
22
+ # s2 = DRb::DRbServer.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
+ # DRb.start_service 'drbunix:', nil # an anonymous server
30
+ # gw = DRbObject.new nil, 'drbunix:/path/to/gateway'
31
+ # gw[:unix] = some_service
32
+ # DRb.thread.join
33
+
34
+ class GWIdConv < DRbIdConv
35
+ def to_obj(ref) # :nodoc:
36
+ if Array === ref && ref[0] == :DRbObject
37
+ return DRbObject.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 DRbObject # :nodoc:
74
+ def self._load(s)
75
+ uri, ref = Marshal.load(s)
76
+ if DRb.uri == uri
77
+ return ref ? DRb.to_obj(ref) : DRb.front
78
+ end
79
+
80
+ self.new_with(DRb.uri, [:DRbObject, uri, ref])
81
+ end
82
+
83
+ def _dump(lv)
84
+ if DRb.uri == @uri
85
+ if Array === @ref && @ref[0] == :DRbObject
86
+ Marshal.dump([@ref[1], @ref[2]])
87
+ else
88
+ Marshal.dump([@uri, @ref]) # ??
89
+ end
90
+ else
91
+ Marshal.dump([DRb.uri, [:DRbObject, @uri, @ref]])
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ =begin
98
+ DRb.install_id_conv(DRb::GWIdConv.new)
99
+
100
+ front = DRb::GW.new
101
+
102
+ s1 = DRb::DRbServer.new('drbunix:/tmp/gw_b_a', front)
103
+ s2 = DRb::DRbServer.new('drbunix:/tmp/gw_b_c', front)
104
+
105
+ s1.thread.join
106
+ s2.thread.join
107
+ =end
108
+
109
+ =begin
110
+ # foo.rb
111
+
112
+ require 'drb/drb'
113
+
114
+ class Foo
115
+ include DRbUndumped
116
+ def initialize(name, peer=nil)
117
+ @name = name
118
+ @peer = peer
119
+ end
120
+
121
+ def ping(obj)
122
+ puts "#{@name}: ping: #{obj.inspect}"
123
+ @peer.ping(self) if @peer
124
+ end
125
+ end
126
+ =end
127
+
128
+ =begin
129
+ # gw_a.rb
130
+ require 'drb/unix'
131
+ require 'foo'
132
+
133
+ obj = Foo.new('a')
134
+ DRb.start_service("drbunix:/tmp/gw_a", obj)
135
+
136
+ robj = DRbObject.new_with_uri('drbunix:/tmp/gw_b_a')
137
+ robj[:a] = obj
138
+
139
+ DRb.thread.join
140
+ =end
141
+
142
+ =begin
143
+ # gw_c.rb
144
+ require 'drb/unix'
145
+ require 'foo'
146
+
147
+ foo = Foo.new('c', nil)
148
+
149
+ DRb.start_service("drbunix:/tmp/gw_c", nil)
150
+
151
+ robj = DRbObject.new_with_uri("drbunix:/tmp/gw_b_c")
152
+
153
+ puts "c->b"
154
+ a = robj[:a]
155
+ sleep 2
156
+
157
+ a.ping(foo)
158
+
159
+ DRb.thread.join
160
+ =end
161
+
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: false
2
+ # for ruby-1.8.0
3
+
4
+ module DRb # :nodoc: all
5
+ class DRbServer
6
+ module InvokeMethod18Mixin
7
+ def block_yield(x)
8
+ if x.size == 1 && x[0].class == Array
9
+ x[0] = DRbArray.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 DRb
5
+ # The Observable module extended to DRb. See Observable for details.
6
+ module DRbObservable
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,344 @@
1
+ # frozen_string_literal: false
2
+ require 'socket'
3
+ require 'openssl'
4
+ require_relative 'drb'
5
+ require 'singleton'
6
+
7
+ module DRb
8
+
9
+ # The protocol for DRb over an SSL socket
10
+ #
11
+ # The URI for a DRb socket over SSL is:
12
+ # <code>drbssl://<host>:<port>?<option></code>. The option is optional
13
+ class DRbSSLSocket < DRbTCPSocket
14
+
15
+ # SSLConfig handles the needed SSL information for establishing a
16
+ # DRbSSLSocket connection, including generating the X509 / RSA pair.
17
+ #
18
+ # An instance of this config can be passed to DRbSSLSocket.new,
19
+ # DRbSSLSocket.open and DRbSSLSocket.open_server
20
+ #
21
+ # See DRb::DRbSSLSocket::SSLConfig.new for more details
22
+ class SSLConfig
23
+
24
+ # Default values for a SSLConfig instance.
25
+ #
26
+ # See DRb::DRbSSLSocket::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 DRb::DRbSSLSocket::SSLConfig instance
44
+ #
45
+ # The DRb::DRbSSLSocket 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 'drb/ssl'
111
+ # c = DRb::DRbSSLSocket::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 'drb/ssl'
122
+ # c = DRb::DRbSSLSocket::SSLConfig.new({
123
+ # :SSLCertName => [["CN" => DRb::DRbSSLSocket.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(2048){|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, "SHA256")
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 drbssl://...
226
+ #
227
+ # Raises DRbBadScheme or DRbBadURI if +uri+ is not matching or malformed
228
+ def self.parse_uri(uri) # :nodoc:
229
+ if /\Adrbssl:\/\/(.*?):(\d+)(\?(.*))?\z/ =~ uri
230
+ host = $1
231
+ port = $2.to_i
232
+ option = $4
233
+ [host, port, option]
234
+ else
235
+ raise(DRbBadScheme, uri) unless uri.start_with?('drbssl:')
236
+ raise(DRbBadURI, 'can\'t parse uri:' + uri)
237
+ end
238
+ end
239
+
240
+ # Return an DRb::DRbSSLSocket instance as a client-side connection,
241
+ # with the SSL connected. This is called from DRb::start_service or while
242
+ # connecting to a remote object:
243
+ #
244
+ # DRb.start_service 'drbssl://localhost:0', front, config
245
+ #
246
+ # +uri+ is the URI we are connected to,
247
+ # <code>'drbssl://localhost:0'</code> above, +config+ is our
248
+ # configuration. Either a Hash or DRb::DRbSSLSocket::SSLConfig
249
+ def self.open(uri, config)
250
+ host, port, = parse_uri(uri)
251
+ soc = TCPSocket.open(host, port)
252
+ ssl_conf = SSLConfig::new(config)
253
+ ssl_conf.setup_ssl_context
254
+ ssl = ssl_conf.connect(soc)
255
+ self.new(uri, ssl, ssl_conf, true)
256
+ end
257
+
258
+ # Returns a DRb::DRbSSLSocket instance as a server-side connection, with
259
+ # the SSL connected. This is called from DRb::start_service or while
260
+ # connecting to a remote object:
261
+ #
262
+ # DRb.start_service 'drbssl://localhost:0', front, config
263
+ #
264
+ # +uri+ is the URI we are connected to,
265
+ # <code>'drbssl://localhost:0'</code> above, +config+ is our
266
+ # configuration. Either a Hash or DRb::DRbSSLSocket::SSLConfig
267
+ def self.open_server(uri, config)
268
+ uri = 'drbssl://:0' unless uri
269
+ host, port, = parse_uri(uri)
270
+ if host.size == 0
271
+ host = getservername
272
+ soc = open_server_inaddr_any(host, port)
273
+ else
274
+ soc = TCPServer.open(host, port)
275
+ end
276
+ port = soc.addr[1] if port == 0
277
+ @uri = "drbssl://#{host}:#{port}"
278
+
279
+ ssl_conf = SSLConfig.new(config)
280
+ ssl_conf.setup_certificate
281
+ ssl_conf.setup_ssl_context
282
+ self.new(@uri, soc, ssl_conf, false)
283
+ end
284
+
285
+ # This is a convenience method to parse +uri+ and separate out any
286
+ # additional options appended in the +uri+.
287
+ #
288
+ # Returns an option-less uri and the option => [uri,option]
289
+ #
290
+ # The +config+ is completely unused, so passing nil is sufficient.
291
+ def self.uri_option(uri, config) # :nodoc:
292
+ host, port, option = parse_uri(uri)
293
+ return "drbssl://#{host}:#{port}", option
294
+ end
295
+
296
+ # Create a DRb::DRbSSLSocket instance.
297
+ #
298
+ # +uri+ is the URI we are connected to.
299
+ # +soc+ is the tcp socket we are bound to.
300
+ # +config+ is our configuration. Either a Hash or SSLConfig
301
+ # +is_established+ is a boolean of whether +soc+ is currently established
302
+ #
303
+ # This is called automatically based on the DRb protocol.
304
+ def initialize(uri, soc, config, is_established)
305
+ @ssl = is_established ? soc : nil
306
+ super(uri, soc.to_io, config)
307
+ end
308
+
309
+ # Returns the SSL stream
310
+ def stream; @ssl; end # :nodoc:
311
+
312
+ # Closes the SSL stream before closing the dRuby connection.
313
+ def close # :nodoc:
314
+ if @ssl
315
+ @ssl.close
316
+ @ssl = nil
317
+ end
318
+ super
319
+ end
320
+
321
+ def accept # :nodoc:
322
+ begin
323
+ while true
324
+ soc = accept_or_shutdown
325
+ return nil unless soc
326
+ break if (@acl ? @acl.allow_socket?(soc) : true)
327
+ soc.close
328
+ end
329
+ begin
330
+ ssl = @config.accept(soc)
331
+ rescue Exception
332
+ soc.close
333
+ raise
334
+ end
335
+ self.class.new(uri, ssl, @config, true)
336
+ rescue OpenSSL::SSL::SSLError
337
+ warn("#{$!.message} (#{$!.class})", uplevel: 0) if @config[:verbose]
338
+ retry
339
+ end
340
+ end
341
+ end
342
+
343
+ DRbProtocol.add_protocol(DRbSSLSocket)
344
+ end