rubysl-drb 1.0.0 → 2.0.1
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/.travis.yml +3 -2
- data/lib/drb/acl.rb +128 -24
- data/lib/drb/drb.rb +349 -299
- data/lib/drb/eq.rb +1 -3
- data/lib/drb/extserv.rb +16 -7
- data/lib/drb/extservm.rb +17 -13
- data/lib/drb/gw.rb +40 -2
- data/lib/drb/invokemethod.rb +6 -6
- data/lib/drb/observer.rb +13 -10
- data/lib/drb/ssl.rb +246 -93
- data/lib/drb/timeridconv.rb +53 -43
- data/lib/drb/unix.rb +32 -25
- data/lib/rubysl/drb/version.rb +1 -1
- data/rubysl-drb.gemspec +3 -1
- data/spec/drbserver/here_spec.rb +6 -0
- data/spec/drbserver/verbose_spec.rb +4 -4
- metadata +20 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 213ea322bd994875b60a34c5757494df17eff965
|
4
|
+
data.tar.gz: d65733cb1206a3f02b1c2fc0da9ce5bfdc33c0c3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce34af436338b849c3645ed0b9a5ad5726741881d5c5ee15b3c611b340129b605649a518a90d2cfdc2e1e608fcaa38601e6659d6abe13a3ebd8ff9639d08a6bb
|
7
|
+
data.tar.gz: 4174c5e60f34958c2cb6d8ab287e82ff7a55aa7bd30327de311f242cc6170157c53318ae23e1e4330b0a36359bc1afdf0435487c85de398a2b09c06e23a0032b
|
data/.travis.yml
CHANGED
data/lib/drb/acl.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# acl-2.0 - simple Access Control List
|
2
|
-
#
|
3
1
|
# Copyright (c) 2000,2002,2003 Masatoshi SEKI
|
4
2
|
#
|
5
3
|
# acl.rb is copyrighted free software by Masatoshi SEKI.
|
@@ -7,80 +5,170 @@
|
|
7
5
|
|
8
6
|
require 'ipaddr'
|
9
7
|
|
8
|
+
##
|
9
|
+
# Simple Access Control Lists.
|
10
|
+
#
|
11
|
+
# Access control lists are composed of "allow" and "deny" halves to control
|
12
|
+
# access. Use "all" or "*" to match any address. To match a specific address
|
13
|
+
# use any address or address mask that IPAddr can understand.
|
14
|
+
#
|
15
|
+
# Example:
|
16
|
+
#
|
17
|
+
# list = %w[
|
18
|
+
# deny all
|
19
|
+
# allow 192.168.1.1
|
20
|
+
# allow ::ffff:192.168.1.2
|
21
|
+
# allow 192.168.1.3
|
22
|
+
# ]
|
23
|
+
#
|
24
|
+
# # From Socket#peeraddr, see also ACL#allow_socket?
|
25
|
+
# addr = ["AF_INET", 10, "lc630", "192.168.1.3"]
|
26
|
+
#
|
27
|
+
# acl = ACL.new
|
28
|
+
# p acl.allow_addr?(addr) # => true
|
29
|
+
#
|
30
|
+
# acl = ACL.new(list, ACL::DENY_ALLOW)
|
31
|
+
# p acl.allow_addr?(addr) # => true
|
32
|
+
|
10
33
|
class ACL
|
34
|
+
|
35
|
+
##
|
36
|
+
# The current version of ACL
|
37
|
+
|
11
38
|
VERSION=["2.0.0"]
|
39
|
+
|
40
|
+
##
|
41
|
+
# An entry in an ACL
|
42
|
+
|
12
43
|
class ACLEntry
|
44
|
+
|
45
|
+
##
|
46
|
+
# Creates a new entry using +str+.
|
47
|
+
#
|
48
|
+
# +str+ may be "*" or "all" to match any address, an IP address string
|
49
|
+
# to match a specific address, an IP address mask per IPAddr, or one
|
50
|
+
# containing "*" to match part of an IPv4 address.
|
51
|
+
|
13
52
|
def initialize(str)
|
14
53
|
if str == '*' or str == 'all'
|
15
|
-
|
54
|
+
@pat = [:all]
|
16
55
|
elsif str.include?('*')
|
17
56
|
@pat = [:name, dot_pat(str)]
|
18
57
|
else
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
58
|
+
begin
|
59
|
+
@pat = [:ip, IPAddr.new(str)]
|
60
|
+
rescue ArgumentError
|
61
|
+
@pat = [:name, dot_pat(str)]
|
62
|
+
end
|
24
63
|
end
|
25
64
|
end
|
26
65
|
|
27
66
|
private
|
67
|
+
|
68
|
+
##
|
69
|
+
# Creates a regular expression to match IPv4 addresses
|
70
|
+
|
28
71
|
def dot_pat_str(str)
|
29
72
|
list = str.split('.').collect { |s|
|
30
|
-
|
73
|
+
(s == '*') ? '.+' : s
|
31
74
|
}
|
32
75
|
list.join("\\.")
|
33
76
|
end
|
34
77
|
|
35
78
|
private
|
79
|
+
|
80
|
+
##
|
81
|
+
# Creates a Regexp to match an address.
|
82
|
+
|
36
83
|
def dot_pat(str)
|
37
84
|
exp = "^" + dot_pat_str(str) + "$"
|
38
85
|
Regexp.new(exp)
|
39
86
|
end
|
40
87
|
|
41
88
|
public
|
89
|
+
|
90
|
+
##
|
91
|
+
# Matches +addr+ against this entry.
|
92
|
+
|
42
93
|
def match(addr)
|
43
94
|
case @pat[0]
|
44
95
|
when :all
|
45
|
-
|
96
|
+
true
|
46
97
|
when :ip
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
98
|
+
begin
|
99
|
+
ipaddr = IPAddr.new(addr[3])
|
100
|
+
ipaddr = ipaddr.ipv4_mapped if @pat[1].ipv6? && ipaddr.ipv4?
|
101
|
+
rescue ArgumentError
|
102
|
+
return false
|
103
|
+
end
|
104
|
+
(@pat[1].include?(ipaddr)) ? true : false
|
54
105
|
when :name
|
55
|
-
|
106
|
+
(@pat[1] =~ addr[2]) ? true : false
|
56
107
|
else
|
57
|
-
|
108
|
+
false
|
58
109
|
end
|
59
110
|
end
|
60
111
|
end
|
61
112
|
|
113
|
+
##
|
114
|
+
# A list of ACLEntry objects. Used to implement the allow and deny halves
|
115
|
+
# of an ACL
|
116
|
+
|
62
117
|
class ACLList
|
118
|
+
|
119
|
+
##
|
120
|
+
# Creates an empty ACLList
|
121
|
+
|
63
122
|
def initialize
|
64
123
|
@list = []
|
65
124
|
end
|
66
125
|
|
67
126
|
public
|
127
|
+
|
128
|
+
##
|
129
|
+
# Matches +addr+ against each ACLEntry in this list.
|
130
|
+
|
68
131
|
def match(addr)
|
69
132
|
@list.each do |e|
|
70
|
-
|
133
|
+
return true if e.match(addr)
|
71
134
|
end
|
72
135
|
false
|
73
136
|
end
|
74
137
|
|
75
138
|
public
|
139
|
+
|
140
|
+
##
|
141
|
+
# Adds +str+ as an ACLEntry in this list
|
142
|
+
|
76
143
|
def add(str)
|
77
144
|
@list.push(ACLEntry.new(str))
|
78
145
|
end
|
146
|
+
|
79
147
|
end
|
80
148
|
|
149
|
+
##
|
150
|
+
# Default to deny
|
151
|
+
|
81
152
|
DENY_ALLOW = 0
|
153
|
+
|
154
|
+
##
|
155
|
+
# Default to allow
|
156
|
+
|
82
157
|
ALLOW_DENY = 1
|
83
158
|
|
159
|
+
##
|
160
|
+
# Creates a new ACL from +list+ with an evaluation +order+ of DENY_ALLOW or
|
161
|
+
# ALLOW_DENY.
|
162
|
+
#
|
163
|
+
# An ACL +list+ is an Array of "allow" or "deny" and an address or address
|
164
|
+
# mask or "all" or "*" to match any address:
|
165
|
+
#
|
166
|
+
# %w[
|
167
|
+
# deny all
|
168
|
+
# allow 192.0.2.2
|
169
|
+
# allow 192.0.2.128/26
|
170
|
+
# ]
|
171
|
+
|
84
172
|
def initialize(list=nil, order = DENY_ALLOW)
|
85
173
|
@order = order
|
86
174
|
@deny = ACLList.new
|
@@ -89,11 +177,22 @@ class ACL
|
|
89
177
|
end
|
90
178
|
|
91
179
|
public
|
180
|
+
|
181
|
+
##
|
182
|
+
# Allow connections from Socket +soc+?
|
183
|
+
|
92
184
|
def allow_socket?(soc)
|
93
185
|
allow_addr?(soc.peeraddr)
|
94
186
|
end
|
95
187
|
|
96
188
|
public
|
189
|
+
|
190
|
+
##
|
191
|
+
# Allow connections from addrinfo +addr+? It must be formatted like
|
192
|
+
# Socket#peeraddr:
|
193
|
+
#
|
194
|
+
# ["AF_INET", 10, "lc630", "192.0.2.1"]
|
195
|
+
|
97
196
|
def allow_addr?(addr)
|
98
197
|
case @order
|
99
198
|
when DENY_ALLOW
|
@@ -110,27 +209,32 @@ class ACL
|
|
110
209
|
end
|
111
210
|
|
112
211
|
public
|
212
|
+
|
213
|
+
##
|
214
|
+
# Adds +list+ of ACL entries to this ACL.
|
215
|
+
|
113
216
|
def install_list(list)
|
114
217
|
i = 0
|
115
218
|
while i < list.size
|
116
219
|
permission, domain = list.slice(i,2)
|
117
220
|
case permission.downcase
|
118
221
|
when 'allow'
|
119
|
-
|
222
|
+
@allow.add(domain)
|
120
223
|
when 'deny'
|
121
|
-
|
224
|
+
@deny.add(domain)
|
122
225
|
else
|
123
|
-
|
226
|
+
raise "Invalid ACL entry #{list.to_s}"
|
124
227
|
end
|
125
228
|
i += 2
|
126
229
|
end
|
127
230
|
end
|
231
|
+
|
128
232
|
end
|
129
233
|
|
130
234
|
if __FILE__ == $0
|
131
235
|
# example
|
132
236
|
list = %w(deny all
|
133
|
-
|
237
|
+
allow 192.168.1.1
|
134
238
|
allow ::ffff:192.168.1.2
|
135
239
|
allow 192.168.1.3
|
136
240
|
)
|
data/lib/drb/drb.rb
CHANGED
@@ -18,7 +18,7 @@
|
|
18
18
|
#
|
19
19
|
# The Ruby standard library contains the core classes of the dRuby package.
|
20
20
|
# However, the full package also includes access control lists and the
|
21
|
-
# Rinda tuple-space distributed task management system, as well as a
|
21
|
+
# Rinda tuple-space distributed task management system, as well as a
|
22
22
|
# large number of samples. The full dRuby package can be downloaded from
|
23
23
|
# the dRuby home page (see *References*).
|
24
24
|
#
|
@@ -34,17 +34,11 @@
|
|
34
34
|
# [http://www2a.biglobe.ne.jp/~seki/ruby/druby.en.html]
|
35
35
|
# The English version of the dRuby home page.
|
36
36
|
#
|
37
|
-
# [http://
|
38
|
-
#
|
37
|
+
# [http://pragprog.com/book/sidruby/the-druby-book]
|
38
|
+
# The dRuby Book: Distributed and Parallel Computing with Ruby
|
39
|
+
# by Masatoshi Seki and Makoto Inoue
|
39
40
|
#
|
40
|
-
# [http://www.
|
41
|
-
# A tutorial introduction to dRuby in Linux Magazine by Dave Thomas.
|
42
|
-
# Includes a discussion of Rinda.
|
43
|
-
#
|
44
|
-
# [http://www.eng.cse.dmu.ac.uk/~hgs/ruby/dRuby/]
|
45
|
-
# Links to English-language Ruby material collected by Hugh Sasse.
|
46
|
-
#
|
47
|
-
# [http://www.rubycentral.com/book/ospace.html]
|
41
|
+
# [http://www.ruby-doc.org/docs/ProgrammingRuby/html/ospace.html]
|
48
42
|
# The chapter from *Programming* *Ruby* by Dave Thomas and Andy Hunt
|
49
43
|
# which discusses dRuby.
|
50
44
|
#
|
@@ -121,7 +115,7 @@ require 'drb/eq'
|
|
121
115
|
# are forwarded to the local object, as described in the discussion of
|
122
116
|
# DRbObjects. This has semantics similar to the normal Ruby
|
123
117
|
# pass-by-reference.
|
124
|
-
#
|
118
|
+
#
|
125
119
|
# The easiest way to signal that we want an otherwise marshallable
|
126
120
|
# object to be passed or returned as a DRbObject reference, rather
|
127
121
|
# than marshalled and sent as a copy, is to include the
|
@@ -135,7 +129,7 @@ require 'drb/eq'
|
|
135
129
|
# passed back to the remote execution context to be collected, before
|
136
130
|
# the collected values are finally returned to the local context as
|
137
131
|
# the return value of the method invocation.
|
138
|
-
#
|
132
|
+
#
|
139
133
|
# == Examples of usage
|
140
134
|
#
|
141
135
|
# For more dRuby samples, see the +samples+ directory in the full
|
@@ -148,33 +142,33 @@ require 'drb/eq'
|
|
148
142
|
# starting the server code first.
|
149
143
|
#
|
150
144
|
# ==== Server code
|
151
|
-
#
|
145
|
+
#
|
152
146
|
# require 'drb/drb'
|
153
|
-
#
|
147
|
+
#
|
154
148
|
# # The URI for the server to connect to
|
155
|
-
# URI="druby://localhost:8787"
|
156
|
-
#
|
149
|
+
# URI="druby://localhost:8787"
|
150
|
+
#
|
157
151
|
# class TimeServer
|
158
|
-
#
|
152
|
+
#
|
159
153
|
# def get_current_time
|
160
154
|
# return Time.now
|
161
155
|
# end
|
162
|
-
#
|
156
|
+
#
|
163
157
|
# end
|
164
|
-
#
|
158
|
+
#
|
165
159
|
# # The object that handles requests on the server
|
166
160
|
# FRONT_OBJECT=TimeServer.new
|
167
161
|
#
|
168
162
|
# $SAFE = 1 # disable eval() and friends
|
169
|
-
#
|
163
|
+
#
|
170
164
|
# DRb.start_service(URI, FRONT_OBJECT)
|
171
165
|
# # Wait for the drb server thread to finish before exiting.
|
172
166
|
# DRb.thread.join
|
173
167
|
#
|
174
168
|
# ==== Client code
|
175
|
-
#
|
169
|
+
#
|
176
170
|
# require 'drb/drb'
|
177
|
-
#
|
171
|
+
#
|
178
172
|
# # The URI to connect to
|
179
173
|
# SERVER_URI="druby://localhost:8787"
|
180
174
|
#
|
@@ -184,43 +178,43 @@ require 'drb/eq'
|
|
184
178
|
# # as soon as we pass a non-marshallable object as an argument
|
185
179
|
# # to a dRuby call.
|
186
180
|
# DRb.start_service
|
187
|
-
#
|
181
|
+
#
|
188
182
|
# timeserver = DRbObject.new_with_uri(SERVER_URI)
|
189
|
-
# puts timeserver.get_current_time
|
183
|
+
# puts timeserver.get_current_time
|
190
184
|
#
|
191
185
|
# === Remote objects under dRuby
|
192
186
|
#
|
193
187
|
# This example illustrates returning a reference to an object
|
194
188
|
# from a dRuby call. The Logger instances live in the server
|
195
189
|
# process. References to them are returned to the client process,
|
196
|
-
# where methods can be invoked upon them. These methods are
|
190
|
+
# where methods can be invoked upon them. These methods are
|
197
191
|
# executed in the server process.
|
198
192
|
#
|
199
193
|
# ==== Server code
|
200
|
-
#
|
194
|
+
#
|
201
195
|
# require 'drb/drb'
|
202
|
-
#
|
196
|
+
#
|
203
197
|
# URI="druby://localhost:8787"
|
204
|
-
#
|
198
|
+
#
|
205
199
|
# class Logger
|
206
200
|
#
|
207
201
|
# # Make dRuby send Logger instances as dRuby references,
|
208
202
|
# # not copies.
|
209
203
|
# include DRb::DRbUndumped
|
210
|
-
#
|
204
|
+
#
|
211
205
|
# def initialize(n, fname)
|
212
206
|
# @name = n
|
213
207
|
# @filename = fname
|
214
208
|
# end
|
215
|
-
#
|
209
|
+
#
|
216
210
|
# def log(message)
|
217
211
|
# File.open(@filename, "a") do |f|
|
218
212
|
# f.puts("#{Time.now}: #{@name}: #{message}")
|
219
213
|
# end
|
220
214
|
# end
|
221
|
-
#
|
215
|
+
#
|
222
216
|
# end
|
223
|
-
#
|
217
|
+
#
|
224
218
|
# # We have a central object for creating and retrieving loggers.
|
225
219
|
# # This retains a local reference to all loggers created. This
|
226
220
|
# # is so an existing logger can be looked up by name, but also
|
@@ -228,12 +222,12 @@ require 'drb/eq'
|
|
228
222
|
# # reference to an object is not sufficient to prevent it being
|
229
223
|
# # garbage collected!
|
230
224
|
# class LoggerFactory
|
231
|
-
#
|
225
|
+
#
|
232
226
|
# def initialize(bdir)
|
233
227
|
# @basedir = bdir
|
234
228
|
# @loggers = {}
|
235
229
|
# end
|
236
|
-
#
|
230
|
+
#
|
237
231
|
# def get_logger(name)
|
238
232
|
# if !@loggers.has_key? name
|
239
233
|
# # make the filename safe, then declare it to be so
|
@@ -242,34 +236,34 @@ require 'drb/eq'
|
|
242
236
|
# end
|
243
237
|
# return @loggers[name]
|
244
238
|
# end
|
245
|
-
#
|
239
|
+
#
|
246
240
|
# end
|
247
|
-
#
|
241
|
+
#
|
248
242
|
# FRONT_OBJECT=LoggerFactory.new("/tmp/dlog")
|
249
243
|
#
|
250
244
|
# $SAFE = 1 # disable eval() and friends
|
251
|
-
#
|
245
|
+
#
|
252
246
|
# DRb.start_service(URI, FRONT_OBJECT)
|
253
247
|
# DRb.thread.join
|
254
248
|
#
|
255
249
|
# ==== Client code
|
256
250
|
#
|
257
251
|
# require 'drb/drb'
|
258
|
-
#
|
252
|
+
#
|
259
253
|
# SERVER_URI="druby://localhost:8787"
|
260
254
|
#
|
261
255
|
# DRb.start_service
|
262
|
-
#
|
256
|
+
#
|
263
257
|
# log_service=DRbObject.new_with_uri(SERVER_URI)
|
264
|
-
#
|
258
|
+
#
|
265
259
|
# ["loga", "logb", "logc"].each do |logname|
|
266
|
-
#
|
260
|
+
#
|
267
261
|
# logger=log_service.get_logger(logname)
|
268
|
-
#
|
262
|
+
#
|
269
263
|
# logger.log("Hello, world!")
|
270
264
|
# logger.log("Goodbye, world!")
|
271
265
|
# logger.log("=== EOT ===")
|
272
|
-
#
|
266
|
+
#
|
273
267
|
# end
|
274
268
|
#
|
275
269
|
# == Security
|
@@ -288,9 +282,9 @@ require 'drb/eq'
|
|
288
282
|
# ro.instance_eval("`rm -rf *`")
|
289
283
|
#
|
290
284
|
# The dangers posed by instance_eval and friends are such that a
|
291
|
-
# DRbServer should generally be run with $SAFE set to at least
|
292
|
-
# level 1. This will disable eval() and related calls on strings
|
293
|
-
# passed across the wire. The sample usage code given above follows
|
285
|
+
# DRbServer should generally be run with $SAFE set to at least
|
286
|
+
# level 1. This will disable eval() and related calls on strings
|
287
|
+
# passed across the wire. The sample usage code given above follows
|
294
288
|
# this practice.
|
295
289
|
#
|
296
290
|
# A DRbServer can be configured with an access control list to
|
@@ -360,7 +354,7 @@ module DRb
|
|
360
354
|
#
|
361
355
|
# This, the default implementation, uses an object's local ObjectSpace
|
362
356
|
# __id__ as its id. This means that an object's identification over
|
363
|
-
# drb remains valid only while that object instance remains alive
|
357
|
+
# drb remains valid only while that object instance remains alive
|
364
358
|
# within the server runtime.
|
365
359
|
#
|
366
360
|
# For alternative mechanisms, see DRb::TimerIdConv in rdb/timeridconv.rb
|
@@ -374,7 +368,7 @@ module DRb
|
|
374
368
|
def to_obj(ref)
|
375
369
|
ObjectSpace._id2ref(ref)
|
376
370
|
end
|
377
|
-
|
371
|
+
|
378
372
|
# Convert an object into a reference id.
|
379
373
|
#
|
380
374
|
# This implementation returns the object's __id__ in the local
|
@@ -390,7 +384,7 @@ module DRb
|
|
390
384
|
# called over drb, then the object remains in the server space
|
391
385
|
# and a reference to the object is returned, rather than the
|
392
386
|
# object being marshalled and moved into the client space.
|
393
|
-
module DRbUndumped
|
387
|
+
module DRbUndumped
|
394
388
|
def _dump(dummy) # :nodoc:
|
395
389
|
raise TypeError, 'can\'t dump'
|
396
390
|
end
|
@@ -424,7 +418,7 @@ module DRb
|
|
424
418
|
def self._load(s) # :nodoc:
|
425
419
|
Marshal::load(s)
|
426
420
|
end
|
427
|
-
|
421
|
+
|
428
422
|
def _dump(lv) # :nodoc:
|
429
423
|
Marshal::dump(@unknown)
|
430
424
|
end
|
@@ -432,6 +426,8 @@ module DRb
|
|
432
426
|
|
433
427
|
# An exception wrapping an error object
|
434
428
|
class DRbRemoteError < DRbError
|
429
|
+
|
430
|
+
# Creates a new remote error that wraps the Exception +error+
|
435
431
|
def initialize(error)
|
436
432
|
@reason = error.class.to_s
|
437
433
|
super("#{error.message} (#{error.class})")
|
@@ -456,21 +452,21 @@ module DRb
|
|
456
452
|
# +name+ attribute. The marshalled object is held in the +buf+
|
457
453
|
# attribute.
|
458
454
|
class DRbUnknown
|
459
|
-
|
455
|
+
|
460
456
|
# Create a new DRbUnknown object.
|
461
457
|
#
|
462
458
|
# +buf+ is a string containing a marshalled object that could not
|
463
|
-
# be unmarshalled. +err+ is the error message that was raised
|
459
|
+
# be unmarshalled. +err+ is the error message that was raised
|
464
460
|
# when the unmarshalling failed. It is used to determine the
|
465
461
|
# name of the unmarshalled object.
|
466
462
|
def initialize(err, buf)
|
467
463
|
case err.to_s
|
468
464
|
when /uninitialized constant (\S+)/
|
469
|
-
|
465
|
+
@name = $1
|
470
466
|
when /undefined class\/module (\S+)/
|
471
|
-
|
467
|
+
@name = $1
|
472
468
|
else
|
473
|
-
|
469
|
+
@name = nil
|
474
470
|
end
|
475
471
|
@buf = buf
|
476
472
|
end
|
@@ -486,9 +482,9 @@ module DRb
|
|
486
482
|
|
487
483
|
def self._load(s) # :nodoc:
|
488
484
|
begin
|
489
|
-
|
485
|
+
Marshal::load(s)
|
490
486
|
rescue NameError, ArgumentError
|
491
|
-
|
487
|
+
DRbUnknown.new($!, s)
|
492
488
|
end
|
493
489
|
end
|
494
490
|
|
@@ -499,7 +495,7 @@ module DRb
|
|
499
495
|
# Attempt to load the wrapped marshalled object again.
|
500
496
|
#
|
501
497
|
# If the class of the object is now known locally, the object
|
502
|
-
# will be unmarshalled and returned. Otherwise, a new
|
498
|
+
# will be unmarshalled and returned. Otherwise, a new
|
503
499
|
# but identical DRbUnknown object will be returned.
|
504
500
|
def reload
|
505
501
|
self.class._load(@buf)
|
@@ -511,27 +507,36 @@ module DRb
|
|
511
507
|
end
|
512
508
|
end
|
513
509
|
|
510
|
+
# An Array wrapper that can be sent to another server via DRb.
|
511
|
+
#
|
512
|
+
# All entries in the array will be dumped or be references that point to
|
513
|
+
# the local server.
|
514
|
+
|
514
515
|
class DRbArray
|
516
|
+
|
517
|
+
# Creates a new DRbArray that either dumps or wraps all the items in the
|
518
|
+
# Array +ary+ so they can be loaded by a remote DRb server.
|
519
|
+
|
515
520
|
def initialize(ary)
|
516
|
-
@ary = ary.collect { |obj|
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
521
|
+
@ary = ary.collect { |obj|
|
522
|
+
if obj.kind_of? DRbUndumped
|
523
|
+
DRbObject.new(obj)
|
524
|
+
else
|
525
|
+
begin
|
526
|
+
Marshal.dump(obj)
|
527
|
+
obj
|
528
|
+
rescue
|
529
|
+
DRbObject.new(obj)
|
530
|
+
end
|
531
|
+
end
|
527
532
|
}
|
528
533
|
end
|
529
534
|
|
530
|
-
def self._load(s)
|
535
|
+
def self._load(s) # :nodoc:
|
531
536
|
Marshal::load(s)
|
532
537
|
end
|
533
538
|
|
534
|
-
def _dump(lv)
|
539
|
+
def _dump(lv) # :nodoc:
|
535
540
|
Marshal.dump(@ary)
|
536
541
|
end
|
537
542
|
end
|
@@ -554,16 +559,16 @@ module DRb
|
|
554
559
|
def dump(obj, error=false) # :nodoc:
|
555
560
|
obj = make_proxy(obj, error) if obj.kind_of? DRbUndumped
|
556
561
|
begin
|
557
|
-
|
562
|
+
str = Marshal::dump(obj)
|
558
563
|
rescue
|
559
|
-
|
564
|
+
str = Marshal::dump(make_proxy(obj, error))
|
560
565
|
end
|
561
566
|
[str.size].pack('N') + str
|
562
567
|
end
|
563
568
|
|
564
569
|
def load(soc) # :nodoc:
|
565
570
|
begin
|
566
|
-
sz = soc.read(4)
|
571
|
+
sz = soc.read(4) # sizeof (N)
|
567
572
|
rescue
|
568
573
|
raise(DRbConnError, $!.message, $!.backtrace)
|
569
574
|
end
|
@@ -600,23 +605,23 @@ module DRb
|
|
600
605
|
ary.push(dump(msg_id.id2name))
|
601
606
|
ary.push(dump(arg.length))
|
602
607
|
arg.each do |e|
|
603
|
-
|
608
|
+
ary.push(dump(e))
|
604
609
|
end
|
605
610
|
ary.push(dump(b))
|
606
611
|
stream.write(ary.join(''))
|
607
612
|
rescue
|
608
613
|
raise(DRbConnError, $!.message, $!.backtrace)
|
609
614
|
end
|
610
|
-
|
615
|
+
|
611
616
|
def recv_request(stream) # :nodoc:
|
612
617
|
ref = load(stream)
|
613
618
|
ro = DRb.to_obj(ref)
|
614
619
|
msg = load(stream)
|
615
620
|
argc = load(stream)
|
616
|
-
raise
|
621
|
+
raise(DRbConnError, "too many arguments") if @argc_limit < argc
|
617
622
|
argv = Array.new(argc, nil)
|
618
623
|
argc.times do |n|
|
619
|
-
|
624
|
+
argv[n] = load(stream)
|
620
625
|
end
|
621
626
|
block = load(stream)
|
622
627
|
return ro, msg, argv, block
|
@@ -635,7 +640,7 @@ module DRb
|
|
635
640
|
end
|
636
641
|
|
637
642
|
private
|
638
|
-
def make_proxy(obj, error=false)
|
643
|
+
def make_proxy(obj, error=false) # :nodoc:
|
639
644
|
if error
|
640
645
|
DRbRemoteError.new(obj)
|
641
646
|
else
|
@@ -656,10 +661,10 @@ module DRb
|
|
656
661
|
# using configuration +config+. Return a
|
657
662
|
# protocol instance for this listener.
|
658
663
|
# [uri_option(uri, config)] Take a URI, possibly containing an option
|
659
|
-
# component (e.g. a trailing '?param=val'),
|
664
|
+
# component (e.g. a trailing '?param=val'),
|
660
665
|
# and return a [uri, option] tuple.
|
661
666
|
#
|
662
|
-
# All of these methods should raise a DRbBadScheme error if the URI
|
667
|
+
# All of these methods should raise a DRbBadScheme error if the URI
|
663
668
|
# does not identify the protocol they support (e.g. "druby:" for
|
664
669
|
# the standard Ruby protocol). This is how the DRbProtocol module,
|
665
670
|
# given a URI, determines which protocol implementation serves that
|
@@ -675,14 +680,14 @@ module DRb
|
|
675
680
|
#
|
676
681
|
# The protocol instance returned by #open must have the following methods:
|
677
682
|
#
|
678
|
-
# [send_request (ref, msg_id, arg, b)]
|
683
|
+
# [send_request (ref, msg_id, arg, b)]
|
679
684
|
# Send a request to +ref+ with the given message id and arguments.
|
680
685
|
# This is most easily implemented by calling DRbMessage.send_request,
|
681
686
|
# providing a stream that sits on top of the current protocol.
|
682
687
|
# [recv_reply]
|
683
688
|
# Receive a reply from the server and return it as a [success-boolean,
|
684
689
|
# reply-value] pair. This is most easily implemented by calling
|
685
|
-
# DRb.recv_reply, providing a stream that sits on top of the
|
690
|
+
# DRb.recv_reply, providing a stream that sits on top of the
|
686
691
|
# current protocol.
|
687
692
|
# [alive?]
|
688
693
|
# Is this connection still alive?
|
@@ -725,44 +730,44 @@ module DRb
|
|
725
730
|
# URI by raising a DRbBadScheme error. If no protocol recognises the
|
726
731
|
# URI, then a DRbBadURI error is raised. If a protocol accepts the
|
727
732
|
# URI, but an error occurs in opening it, a DRbConnError is raised.
|
728
|
-
def open(uri, config, first=true)
|
733
|
+
def open(uri, config, first=true)
|
729
734
|
@protocol.each do |prot|
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
735
|
+
begin
|
736
|
+
return prot.open(uri, config)
|
737
|
+
rescue DRbBadScheme
|
738
|
+
rescue DRbConnError
|
739
|
+
raise($!)
|
740
|
+
rescue
|
741
|
+
raise(DRbConnError, "#{uri} - #{$!.inspect}")
|
742
|
+
end
|
738
743
|
end
|
739
744
|
if first && (config[:auto_load] != false)
|
740
|
-
|
741
|
-
|
745
|
+
auto_load(uri, config)
|
746
|
+
return open(uri, config, false)
|
742
747
|
end
|
743
748
|
raise DRbBadURI, 'can\'t parse uri:' + uri
|
744
749
|
end
|
745
750
|
module_function :open
|
746
751
|
|
747
|
-
# Open a server listening for connections at +uri+ with
|
752
|
+
# Open a server listening for connections at +uri+ with
|
748
753
|
# configuration +config+.
|
749
754
|
#
|
750
755
|
# The DRbProtocol module asks each registered protocol in turn to
|
751
|
-
# try to open a server at the URI. Each protocol signals that it does
|
752
|
-
# not handle that URI by raising a DRbBadScheme error. If no protocol
|
753
|
-
# recognises the URI, then a DRbBadURI error is raised. If a protocol
|
754
|
-
# accepts the URI, but an error occurs in opening it, the underlying
|
756
|
+
# try to open a server at the URI. Each protocol signals that it does
|
757
|
+
# not handle that URI by raising a DRbBadScheme error. If no protocol
|
758
|
+
# recognises the URI, then a DRbBadURI error is raised. If a protocol
|
759
|
+
# accepts the URI, but an error occurs in opening it, the underlying
|
755
760
|
# error is passed on to the caller.
|
756
761
|
def open_server(uri, config, first=true)
|
757
762
|
@protocol.each do |prot|
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
763
|
+
begin
|
764
|
+
return prot.open_server(uri, config)
|
765
|
+
rescue DRbBadScheme
|
766
|
+
end
|
762
767
|
end
|
763
768
|
if first && (config[:auto_load] != false)
|
764
|
-
|
765
|
-
|
769
|
+
auto_load(uri, config)
|
770
|
+
return open_server(uri, config, false)
|
766
771
|
end
|
767
772
|
raise DRbBadURI, 'can\'t parse uri:' + uri
|
768
773
|
end
|
@@ -773,18 +778,18 @@ module DRb
|
|
773
778
|
# The DRbProtocol module asks each registered protocol in turn to
|
774
779
|
# try to parse the URI. Each protocol signals that it does not handle that
|
775
780
|
# URI by raising a DRbBadScheme error. If no protocol recognises the
|
776
|
-
# URI, then a DRbBadURI error is raised.
|
781
|
+
# URI, then a DRbBadURI error is raised.
|
777
782
|
def uri_option(uri, config, first=true)
|
778
783
|
@protocol.each do |prot|
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
784
|
+
begin
|
785
|
+
uri, opt = prot.uri_option(uri, config)
|
786
|
+
# opt = nil if opt == ''
|
787
|
+
return uri, opt
|
788
|
+
rescue DRbBadScheme
|
789
|
+
end
|
785
790
|
end
|
786
791
|
if first && (config[:auto_load] != false)
|
787
|
-
|
792
|
+
auto_load(uri, config)
|
788
793
|
return uri_option(uri, config, false)
|
789
794
|
end
|
790
795
|
raise DRbBadURI, 'can\'t parse uri:' + uri
|
@@ -793,40 +798,49 @@ module DRb
|
|
793
798
|
|
794
799
|
def auto_load(uri, config) # :nodoc:
|
795
800
|
if uri =~ /^drb([a-z0-9]+):/
|
796
|
-
|
801
|
+
require("drb/#{$1}") rescue nil
|
797
802
|
end
|
798
803
|
end
|
799
804
|
module_function :auto_load
|
800
805
|
end
|
801
806
|
|
802
|
-
# The default drb protocol.
|
807
|
+
# The default drb protocol which communicates over a TCP socket.
|
803
808
|
#
|
804
|
-
#
|
809
|
+
# The DRb TCP protocol URI looks like:
|
810
|
+
# <code>druby://<host>:<port>?<option></code>. The option is optional.
|
811
|
+
|
805
812
|
class DRbTCPSocket
|
813
|
+
# :stopdoc:
|
806
814
|
private
|
807
815
|
def self.parse_uri(uri)
|
808
816
|
if uri =~ /^druby:\/\/(.*?):(\d+)(\?(.*))?$/
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
817
|
+
host = $1
|
818
|
+
port = $2.to_i
|
819
|
+
option = $4
|
820
|
+
[host, port, option]
|
813
821
|
else
|
814
|
-
|
815
|
-
|
822
|
+
raise(DRbBadScheme, uri) unless uri =~ /^druby:/
|
823
|
+
raise(DRbBadURI, 'can\'t parse uri:' + uri)
|
816
824
|
end
|
817
825
|
end
|
818
826
|
|
819
827
|
public
|
820
828
|
|
821
|
-
# Open a client connection to +uri+ using configuration
|
829
|
+
# Open a client connection to +uri+ (DRb URI string) using configuration
|
830
|
+
# +config+.
|
831
|
+
#
|
832
|
+
# This can raise DRb::DRbBadScheme or DRb::DRbBadURI if +uri+ is not for a
|
833
|
+
# recognized protocol. See DRb::DRbServer.new for information on built-in
|
834
|
+
# URI protocols.
|
822
835
|
def self.open(uri, config)
|
823
|
-
host, port,
|
836
|
+
host, port, = parse_uri(uri)
|
824
837
|
host.untaint
|
825
838
|
port.untaint
|
826
839
|
soc = TCPSocket.open(host, port)
|
827
840
|
self.new(uri, soc, config)
|
828
841
|
end
|
829
842
|
|
843
|
+
# Returns the hostname of this server
|
830
844
|
def self.getservername
|
831
845
|
host = Socket::gethostname
|
832
846
|
begin
|
@@ -836,34 +850,33 @@ module DRb
|
|
836
850
|
end
|
837
851
|
end
|
838
852
|
|
853
|
+
# For the families available for +host+, returns a TCPServer on +port+.
|
854
|
+
# If +port+ is 0 the first available port is used. IPv4 servers are
|
855
|
+
# preferred over IPv6 servers.
|
839
856
|
def self.open_server_inaddr_any(host, port)
|
840
|
-
infos = Socket::getaddrinfo(host, nil,
|
857
|
+
infos = Socket::getaddrinfo(host, nil,
|
841
858
|
Socket::AF_UNSPEC,
|
842
|
-
Socket::SOCK_STREAM,
|
859
|
+
Socket::SOCK_STREAM,
|
843
860
|
0,
|
844
861
|
Socket::AI_PASSIVE)
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
return TCPServer.open('::', port)
|
851
|
-
else
|
852
|
-
return TCPServer.open(port)
|
853
|
-
end
|
862
|
+
families = Hash[*infos.collect { |af, *_| af }.uniq.zip([]).flatten]
|
863
|
+
return TCPServer.open('0.0.0.0', port) if families.has_key?('AF_INET')
|
864
|
+
return TCPServer.open('::', port) if families.has_key?('AF_INET6')
|
865
|
+
return TCPServer.open(port)
|
866
|
+
# :stopdoc:
|
854
867
|
end
|
855
868
|
|
856
|
-
# Open a server listening for connections at +uri+ using
|
869
|
+
# Open a server listening for connections at +uri+ using
|
857
870
|
# configuration +config+.
|
858
871
|
def self.open_server(uri, config)
|
859
872
|
uri = 'druby://:0' unless uri
|
860
|
-
host, port,
|
873
|
+
host, port, _ = parse_uri(uri)
|
861
874
|
config = {:tcp_original_host => host}.update(config)
|
862
875
|
if host.size == 0
|
863
876
|
host = getservername
|
864
877
|
soc = open_server_inaddr_any(host, port)
|
865
878
|
else
|
866
|
-
|
879
|
+
soc = TCPServer.open(host, port)
|
867
880
|
end
|
868
881
|
port = soc.addr[1] if port == 0
|
869
882
|
config[:tcp_port] = port
|
@@ -899,7 +912,7 @@ module DRb
|
|
899
912
|
def peeraddr
|
900
913
|
@socket.peeraddr
|
901
914
|
end
|
902
|
-
|
915
|
+
|
903
916
|
# Get the socket.
|
904
917
|
def stream; @socket; end
|
905
918
|
|
@@ -907,7 +920,7 @@ module DRb
|
|
907
920
|
def send_request(ref, msg_id, arg, b)
|
908
921
|
@msg.send_request(stream, ref, msg_id, arg, b)
|
909
922
|
end
|
910
|
-
|
923
|
+
|
911
924
|
# On the server side, receive a request from the client.
|
912
925
|
def recv_request
|
913
926
|
@msg.recv_request(stream)
|
@@ -933,19 +946,19 @@ module DRb
|
|
933
946
|
# client-server session.
|
934
947
|
def close
|
935
948
|
if @socket
|
936
|
-
|
937
|
-
|
949
|
+
@socket.close
|
950
|
+
@socket = nil
|
938
951
|
end
|
939
952
|
end
|
940
|
-
|
941
|
-
# On the server side, for an instance returned by #open_server,
|
953
|
+
|
954
|
+
# On the server side, for an instance returned by #open_server,
|
942
955
|
# accept a client connection and return a new instance to handle
|
943
956
|
# the server's side of this client-server session.
|
944
957
|
def accept
|
945
958
|
while true
|
946
|
-
|
947
|
-
|
948
|
-
|
959
|
+
s = @socket.accept
|
960
|
+
break if (@acl ? @acl.allow_socket?(s) : true)
|
961
|
+
s.close
|
949
962
|
end
|
950
963
|
if @config[:tcp_original_host].to_s.size == 0
|
951
964
|
uri = "druby://#{s.addr[3]}:#{@config[:tcp_port]}"
|
@@ -959,8 +972,8 @@ module DRb
|
|
959
972
|
def alive?
|
960
973
|
return false unless @socket
|
961
974
|
if IO.select([@socket], nil, nil, 0)
|
962
|
-
|
963
|
-
|
975
|
+
close
|
976
|
+
return false
|
964
977
|
end
|
965
978
|
true
|
966
979
|
end
|
@@ -981,16 +994,16 @@ module DRb
|
|
981
994
|
end
|
982
995
|
attr :option
|
983
996
|
def to_s; @option; end
|
984
|
-
|
997
|
+
|
985
998
|
def ==(other)
|
986
999
|
return false unless DRbURIOption === other
|
987
1000
|
@option == other.option
|
988
1001
|
end
|
989
|
-
|
1002
|
+
|
990
1003
|
def hash
|
991
1004
|
@option.hash
|
992
1005
|
end
|
993
|
-
|
1006
|
+
|
994
1007
|
alias eql? ==
|
995
1008
|
end
|
996
1009
|
|
@@ -1007,9 +1020,9 @@ module DRb
|
|
1007
1020
|
# created to act as a stub for the remote referenced object.
|
1008
1021
|
def self._load(s)
|
1009
1022
|
uri, ref = Marshal.load(s)
|
1010
|
-
|
1023
|
+
|
1011
1024
|
if DRb.here?(uri)
|
1012
|
-
|
1025
|
+
obj = DRb.to_obj(ref)
|
1013
1026
|
if ((! obj.tainted?) && Thread.current[:drb_untaint])
|
1014
1027
|
Thread.current[:drb_untaint].push(obj)
|
1015
1028
|
end
|
@@ -1019,10 +1032,13 @@ module DRb
|
|
1019
1032
|
self.new_with(uri, ref)
|
1020
1033
|
end
|
1021
1034
|
|
1035
|
+
# Creates a DRb::DRbObject given the reference information to the remote
|
1036
|
+
# host +uri+ and object +ref+.
|
1037
|
+
|
1022
1038
|
def self.new_with(uri, ref)
|
1023
1039
|
it = self.allocate
|
1024
|
-
it.instance_variable_set(
|
1025
|
-
it.instance_variable_set(
|
1040
|
+
it.instance_variable_set(:@uri, uri)
|
1041
|
+
it.instance_variable_set(:@ref, ref)
|
1026
1042
|
it
|
1027
1043
|
end
|
1028
1044
|
|
@@ -1047,17 +1063,17 @@ module DRb
|
|
1047
1063
|
@uri = nil
|
1048
1064
|
@ref = nil
|
1049
1065
|
if obj.nil?
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1066
|
+
return if uri.nil?
|
1067
|
+
@uri, option = DRbProtocol.uri_option(uri, DRb.config)
|
1068
|
+
@ref = DRbURIOption.new(option) unless option.nil?
|
1053
1069
|
else
|
1054
|
-
|
1055
|
-
|
1070
|
+
@uri = uri ? uri : (DRb.uri rescue nil)
|
1071
|
+
@ref = obj ? DRb.to_id(obj) : nil
|
1056
1072
|
end
|
1057
1073
|
end
|
1058
1074
|
|
1059
1075
|
# Get the URI of the remote object.
|
1060
|
-
def __drburi
|
1076
|
+
def __drburi
|
1061
1077
|
@uri
|
1062
1078
|
end
|
1063
1079
|
|
@@ -1069,6 +1085,7 @@ module DRb
|
|
1069
1085
|
undef :to_s
|
1070
1086
|
undef :to_a if respond_to?(:to_a)
|
1071
1087
|
|
1088
|
+
# Routes respond_to? to the referenced remote object.
|
1072
1089
|
def respond_to?(msg_id, priv=false)
|
1073
1090
|
case msg_id
|
1074
1091
|
when :_dump
|
@@ -1080,12 +1097,12 @@ module DRb
|
|
1080
1097
|
end
|
1081
1098
|
end
|
1082
1099
|
|
1083
|
-
# Routes method calls to the referenced object.
|
1100
|
+
# Routes method calls to the referenced remote object.
|
1084
1101
|
def method_missing(msg_id, *a, &b)
|
1085
1102
|
if DRb.here?(@uri)
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1103
|
+
obj = DRb.to_obj(@ref)
|
1104
|
+
DRb.current_server.check_insecure_method(obj, msg_id)
|
1105
|
+
return obj.__send__(msg_id, *a, &b)
|
1089
1106
|
end
|
1090
1107
|
|
1091
1108
|
succ, result = self.class.with_friend(@uri) do
|
@@ -1100,15 +1117,16 @@ module DRb
|
|
1100
1117
|
raise result
|
1101
1118
|
else
|
1102
1119
|
bt = self.class.prepare_backtrace(@uri, result)
|
1103
|
-
|
1120
|
+
result.set_backtrace(bt + caller)
|
1104
1121
|
raise result
|
1105
1122
|
end
|
1106
1123
|
end
|
1107
1124
|
|
1108
|
-
|
1125
|
+
# Given the +uri+ of another host executes the block provided.
|
1126
|
+
def self.with_friend(uri) # :nodoc:
|
1109
1127
|
friend = DRb.fetch_server(uri)
|
1110
1128
|
return yield() unless friend
|
1111
|
-
|
1129
|
+
|
1112
1130
|
save = Thread.current['DRb']
|
1113
1131
|
Thread.current['DRb'] = { 'server' => friend }
|
1114
1132
|
return yield
|
@@ -1116,11 +1134,13 @@ module DRb
|
|
1116
1134
|
Thread.current['DRb'] = save if friend
|
1117
1135
|
end
|
1118
1136
|
|
1119
|
-
|
1137
|
+
# Returns a modified backtrace from +result+ with the +uri+ where each call
|
1138
|
+
# in the backtrace came from.
|
1139
|
+
def self.prepare_backtrace(uri, result) # :nodoc:
|
1120
1140
|
prefix = "(#{uri}) "
|
1121
1141
|
bt = []
|
1122
1142
|
result.backtrace.each do |x|
|
1123
|
-
break if /`__send__'$/ =~ x
|
1143
|
+
break if /`__send__'$/ =~ x
|
1124
1144
|
if /^\(druby:\/\// =~ x
|
1125
1145
|
bt.push(x)
|
1126
1146
|
else
|
@@ -1158,36 +1178,36 @@ module DRb
|
|
1158
1178
|
|
1159
1179
|
def self.open(remote_uri) # :nodoc:
|
1160
1180
|
begin
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1181
|
+
conn = nil
|
1182
|
+
|
1183
|
+
@mutex.synchronize do
|
1184
|
+
#FIXME
|
1185
|
+
new_pool = []
|
1186
|
+
@pool.each do |c|
|
1187
|
+
if conn.nil? and c.uri == remote_uri
|
1188
|
+
conn = c if c.alive?
|
1189
|
+
else
|
1190
|
+
new_pool.push c
|
1191
|
+
end
|
1192
|
+
end
|
1193
|
+
@pool = new_pool
|
1194
|
+
end
|
1195
|
+
|
1196
|
+
conn = self.new(remote_uri) unless conn
|
1197
|
+
succ, result = yield(conn)
|
1198
|
+
return succ, result
|
1179
1199
|
|
1180
1200
|
ensure
|
1181
|
-
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1201
|
+
if conn
|
1202
|
+
if succ
|
1203
|
+
@mutex.synchronize do
|
1204
|
+
@pool.unshift(conn)
|
1205
|
+
@pool.pop.close while @pool.size > POOL_SIZE
|
1206
|
+
end
|
1207
|
+
else
|
1208
|
+
conn.close
|
1209
|
+
end
|
1210
|
+
end
|
1191
1211
|
end
|
1192
1212
|
end
|
1193
1213
|
|
@@ -1247,9 +1267,9 @@ module DRb
|
|
1247
1267
|
@@load_limit = sz
|
1248
1268
|
end
|
1249
1269
|
|
1250
|
-
# Set the default
|
1270
|
+
# Set the default access control list to +acl+. The default ACL is +nil+.
|
1251
1271
|
#
|
1252
|
-
# See #new()
|
1272
|
+
# See also DRb::ACL and #new()
|
1253
1273
|
def self.default_acl(acl)
|
1254
1274
|
@@acl = acl
|
1255
1275
|
end
|
@@ -1261,6 +1281,9 @@ module DRb
|
|
1261
1281
|
@@idconv = idconv
|
1262
1282
|
end
|
1263
1283
|
|
1284
|
+
# Set the default safe level to +level+. The default safe level is 0
|
1285
|
+
#
|
1286
|
+
# See #new for more information.
|
1264
1287
|
def self.default_safe_level(level)
|
1265
1288
|
@@safe_level = level
|
1266
1289
|
end
|
@@ -1271,19 +1294,19 @@ module DRb
|
|
1271
1294
|
def self.verbose=(on)
|
1272
1295
|
@@verbose = on
|
1273
1296
|
end
|
1274
|
-
|
1297
|
+
|
1275
1298
|
# Get the default value of the :verbose option.
|
1276
1299
|
def self.verbose
|
1277
1300
|
@@verbose
|
1278
1301
|
end
|
1279
1302
|
|
1280
1303
|
def self.make_config(hash={}) # :nodoc:
|
1281
|
-
default_config = {
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1304
|
+
default_config = {
|
1305
|
+
:idconv => @@idconv,
|
1306
|
+
:verbose => @@verbose,
|
1307
|
+
:tcp_acl => @@acl,
|
1308
|
+
:load_limit => @@load_limit,
|
1309
|
+
:argc_limit => @@argc_limit,
|
1287
1310
|
:safe_level => @@safe_level
|
1288
1311
|
}
|
1289
1312
|
default_config.update(hash)
|
@@ -1318,6 +1341,9 @@ module DRb
|
|
1318
1341
|
# :argc_limit :: the maximum number of arguments to a remote
|
1319
1342
|
# method accepted by the server. Defaults to
|
1320
1343
|
# 256.
|
1344
|
+
# :safe_level :: The safe level of the DRbServer. The attribute
|
1345
|
+
# sets $SAFE for methods performed in the main_loop.
|
1346
|
+
# Defaults to 0.
|
1321
1347
|
#
|
1322
1348
|
# The default values of these options can be modified on
|
1323
1349
|
# a class-wide basis by the class methods #default_argc_limit,
|
@@ -1334,18 +1360,19 @@ module DRb
|
|
1334
1360
|
# The server will immediately start running in its own thread.
|
1335
1361
|
def initialize(uri=nil, front=nil, config_or_acl=nil)
|
1336
1362
|
if Hash === config_or_acl
|
1337
|
-
|
1363
|
+
config = config_or_acl.dup
|
1338
1364
|
else
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1365
|
+
acl = config_or_acl || @@acl
|
1366
|
+
config = {
|
1367
|
+
:tcp_acl => acl
|
1368
|
+
}
|
1343
1369
|
end
|
1344
1370
|
|
1345
1371
|
@config = self.class.make_config(config)
|
1346
1372
|
|
1347
1373
|
@protocol = DRbProtocol.open_server(uri, @config)
|
1348
1374
|
@uri = @protocol.uri
|
1375
|
+
@exported_uri = [@uri]
|
1349
1376
|
|
1350
1377
|
@front = front
|
1351
1378
|
@idconv = @config[:idconv]
|
@@ -1368,7 +1395,7 @@ module DRb
|
|
1368
1395
|
attr_reader :thread
|
1369
1396
|
|
1370
1397
|
# The front object of the DRbServer.
|
1371
|
-
#
|
1398
|
+
#
|
1372
1399
|
# This object receives remote method calls made on the server's
|
1373
1400
|
# URI alone, with an object id.
|
1374
1401
|
attr_reader :front
|
@@ -1376,6 +1403,10 @@ module DRb
|
|
1376
1403
|
# The configuration of this DRbServer
|
1377
1404
|
attr_reader :config
|
1378
1405
|
|
1406
|
+
# The safe level for this server. This is a number corresponding to
|
1407
|
+
# $SAFE.
|
1408
|
+
#
|
1409
|
+
# The default safe_level is 0
|
1379
1410
|
attr_reader :safe_level
|
1380
1411
|
|
1381
1412
|
# Set whether to operate in verbose mode.
|
@@ -1393,13 +1424,18 @@ module DRb
|
|
1393
1424
|
@thread.alive?
|
1394
1425
|
end
|
1395
1426
|
|
1427
|
+
# Is +uri+ the URI for this server?
|
1428
|
+
def here?(uri)
|
1429
|
+
@exported_uri.include?(uri)
|
1430
|
+
end
|
1431
|
+
|
1396
1432
|
# Stop this server.
|
1397
1433
|
def stop_service
|
1398
1434
|
DRb.remove_server(self)
|
1399
1435
|
if Thread.current['DRb'] && Thread.current['DRb']['server'] == self
|
1400
1436
|
Thread.current['DRb']['stop_service'] = true
|
1401
1437
|
else
|
1402
|
-
@thread.kill
|
1438
|
+
@thread.kill.join
|
1403
1439
|
end
|
1404
1440
|
end
|
1405
1441
|
|
@@ -1417,30 +1453,19 @@ module DRb
|
|
1417
1453
|
end
|
1418
1454
|
|
1419
1455
|
private
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1423
|
-
grp.add(Thread.current)
|
1424
|
-
list = @grp.list
|
1425
|
-
while list.size > 0
|
1426
|
-
list.each do |th|
|
1427
|
-
th.kill if th.alive?
|
1428
|
-
end
|
1429
|
-
list = @grp.list
|
1430
|
-
end
|
1431
|
-
end
|
1432
|
-
end
|
1456
|
+
|
1457
|
+
##
|
1458
|
+
# Starts the DRb main loop in a new thread.
|
1433
1459
|
|
1434
1460
|
def run
|
1435
1461
|
Thread.start do
|
1436
|
-
|
1437
|
-
|
1438
|
-
|
1439
|
-
|
1440
|
-
|
1441
|
-
|
1442
|
-
|
1443
|
-
end
|
1462
|
+
begin
|
1463
|
+
while true
|
1464
|
+
main_loop
|
1465
|
+
end
|
1466
|
+
ensure
|
1467
|
+
@protocol.close if @protocol
|
1468
|
+
end
|
1444
1469
|
end
|
1445
1470
|
end
|
1446
1471
|
|
@@ -1461,7 +1486,7 @@ module DRb
|
|
1461
1486
|
def any_to_s(obj)
|
1462
1487
|
obj.to_s + ":#{obj.class}"
|
1463
1488
|
rescue
|
1464
|
-
sprintf("#<%s:0x%lx>", obj.class, obj.__id__)
|
1489
|
+
sprintf("#<%s:0x%lx>", obj.class, obj.__id__)
|
1465
1490
|
end
|
1466
1491
|
|
1467
1492
|
# Check that a method is callable via dRuby.
|
@@ -1469,37 +1494,37 @@ module DRb
|
|
1469
1494
|
# +obj+ is the object we want to invoke the method on. +msg_id+ is the
|
1470
1495
|
# method name, as a Symbol.
|
1471
1496
|
#
|
1472
|
-
# If the method is an insecure method (see #insecure_method?) a
|
1497
|
+
# If the method is an insecure method (see #insecure_method?) a
|
1473
1498
|
# SecurityError is thrown. If the method is private or undefined,
|
1474
1499
|
# a NameError is thrown.
|
1475
1500
|
def check_insecure_method(obj, msg_id)
|
1476
1501
|
return true if Proc === obj && msg_id == :__drb_yield
|
1477
1502
|
raise(ArgumentError, "#{any_to_s(msg_id)} is not a symbol") unless Symbol == msg_id.class
|
1478
1503
|
raise(SecurityError, "insecure method `#{msg_id}'") if insecure_method?(msg_id)
|
1479
|
-
|
1480
|
-
if obj.private_methods.include?(msg_id
|
1481
|
-
|
1504
|
+
|
1505
|
+
if obj.private_methods.include?(msg_id)
|
1506
|
+
desc = any_to_s(obj)
|
1482
1507
|
raise NoMethodError, "private method `#{msg_id}' called for #{desc}"
|
1483
|
-
elsif obj.protected_methods.include?(msg_id
|
1484
|
-
|
1508
|
+
elsif obj.protected_methods.include?(msg_id)
|
1509
|
+
desc = any_to_s(obj)
|
1485
1510
|
raise NoMethodError, "protected method `#{msg_id}' called for #{desc}"
|
1486
1511
|
else
|
1487
1512
|
true
|
1488
1513
|
end
|
1489
1514
|
end
|
1490
1515
|
public :check_insecure_method
|
1491
|
-
|
1516
|
+
|
1492
1517
|
class InvokeMethod # :nodoc:
|
1493
1518
|
def initialize(drb_server, client)
|
1494
|
-
|
1519
|
+
@drb_server = drb_server
|
1495
1520
|
@safe_level = drb_server.safe_level
|
1496
|
-
|
1521
|
+
@client = client
|
1497
1522
|
end
|
1498
1523
|
|
1499
1524
|
def perform
|
1500
|
-
|
1501
|
-
|
1502
|
-
|
1525
|
+
@result = nil
|
1526
|
+
@succ = false
|
1527
|
+
setup_message
|
1503
1528
|
|
1504
1529
|
if $SAFE < @safe_level
|
1505
1530
|
info = Thread.current['DRb']
|
@@ -1510,7 +1535,7 @@ module DRb
|
|
1510
1535
|
perform_with_block
|
1511
1536
|
}.value
|
1512
1537
|
else
|
1513
|
-
@result = Thread.new {
|
1538
|
+
@result = Thread.new {
|
1514
1539
|
Thread.current['DRb'] = info
|
1515
1540
|
$SAFE = @safe_level
|
1516
1541
|
perform_without_block
|
@@ -1523,45 +1548,45 @@ module DRb
|
|
1523
1548
|
@result = perform_without_block
|
1524
1549
|
end
|
1525
1550
|
end
|
1526
|
-
|
1527
|
-
|
1528
|
-
|
1529
|
-
|
1530
|
-
|
1551
|
+
@succ = true
|
1552
|
+
if @msg_id == :to_ary && @result.class == Array
|
1553
|
+
@result = DRbArray.new(@result)
|
1554
|
+
end
|
1555
|
+
return @succ, @result
|
1531
1556
|
rescue StandardError, ScriptError, Interrupt
|
1532
|
-
|
1533
|
-
|
1557
|
+
@result = $!
|
1558
|
+
return @succ, @result
|
1534
1559
|
end
|
1535
1560
|
|
1536
1561
|
private
|
1537
1562
|
def init_with_client
|
1538
|
-
|
1563
|
+
obj, msg, argv, block = @client.recv_request
|
1539
1564
|
@obj = obj
|
1540
1565
|
@msg_id = msg.intern
|
1541
1566
|
@argv = argv
|
1542
1567
|
@block = block
|
1543
1568
|
end
|
1544
|
-
|
1569
|
+
|
1545
1570
|
def check_insecure_method
|
1546
1571
|
@drb_server.check_insecure_method(@obj, @msg_id)
|
1547
1572
|
end
|
1548
1573
|
|
1549
1574
|
def setup_message
|
1550
|
-
|
1551
|
-
|
1575
|
+
init_with_client
|
1576
|
+
check_insecure_method
|
1552
1577
|
end
|
1553
|
-
|
1578
|
+
|
1554
1579
|
def perform_without_block
|
1555
|
-
|
1580
|
+
if Proc === @obj && @msg_id == :__drb_yield
|
1556
1581
|
if @argv.size == 1
|
1557
|
-
|
1558
|
-
|
1559
|
-
|
1560
|
-
|
1561
|
-
|
1562
|
-
|
1563
|
-
|
1564
|
-
|
1582
|
+
ary = @argv
|
1583
|
+
else
|
1584
|
+
ary = [@argv]
|
1585
|
+
end
|
1586
|
+
ary.collect(&@obj)[0]
|
1587
|
+
else
|
1588
|
+
@obj.__send__(@msg_id, *@argv)
|
1589
|
+
end
|
1565
1590
|
end
|
1566
1591
|
|
1567
1592
|
end
|
@@ -1587,29 +1612,33 @@ module DRb
|
|
1587
1612
|
# or a local method call fails.
|
1588
1613
|
def main_loop
|
1589
1614
|
Thread.start(@protocol.accept) do |client|
|
1590
|
-
|
1591
|
-
|
1592
|
-
|
1593
|
-
|
1594
|
-
|
1595
|
-
|
1596
|
-
|
1597
|
-
|
1598
|
-
|
1599
|
-
|
1600
|
-
|
1601
|
-
|
1602
|
-
|
1603
|
-
|
1604
|
-
|
1605
|
-
|
1615
|
+
@grp.add Thread.current
|
1616
|
+
Thread.current['DRb'] = { 'client' => client ,
|
1617
|
+
'server' => self }
|
1618
|
+
DRb.mutex.synchronize do
|
1619
|
+
client_uri = client.uri
|
1620
|
+
@exported_uri << client_uri unless @exported_uri.include?(client_uri)
|
1621
|
+
end
|
1622
|
+
loop do
|
1623
|
+
begin
|
1624
|
+
succ = false
|
1625
|
+
invoke_method = InvokeMethod.new(self, client)
|
1626
|
+
succ, result = invoke_method.perform
|
1627
|
+
if !succ && verbose
|
1628
|
+
p result
|
1629
|
+
result.backtrace.each do |x|
|
1630
|
+
puts x
|
1631
|
+
end
|
1632
|
+
end
|
1633
|
+
client.send_reply(succ, result) rescue nil
|
1634
|
+
ensure
|
1606
1635
|
client.close unless succ
|
1607
1636
|
if Thread.current['DRb']['stop_service']
|
1608
1637
|
Thread.new { stop_service }
|
1609
1638
|
end
|
1610
1639
|
break unless succ
|
1611
|
-
|
1612
|
-
|
1640
|
+
end
|
1641
|
+
end
|
1613
1642
|
end
|
1614
1643
|
end
|
1615
1644
|
end
|
@@ -1638,7 +1667,7 @@ module DRb
|
|
1638
1667
|
|
1639
1668
|
# The primary local dRuby server.
|
1640
1669
|
#
|
1641
|
-
# This is the server created by the #start_service call.
|
1670
|
+
# This is the server created by the #start_service call.
|
1642
1671
|
attr_accessor :primary_server
|
1643
1672
|
module_function :primary_server=, :primary_server
|
1644
1673
|
|
@@ -1653,8 +1682,8 @@ module DRb
|
|
1653
1682
|
# If the above rule fails to find a server, a DRbServerNotFound
|
1654
1683
|
# error is raised.
|
1655
1684
|
def current_server
|
1656
|
-
drb = Thread.current['DRb']
|
1657
|
-
server = (drb && drb['server']) ? drb['server'] : @primary_server
|
1685
|
+
drb = Thread.current['DRb']
|
1686
|
+
server = (drb && drb['server']) ? drb['server'] : @primary_server
|
1658
1687
|
raise DRbServerNotFound unless server
|
1659
1688
|
return server
|
1660
1689
|
end
|
@@ -1686,7 +1715,8 @@ module DRb
|
|
1686
1715
|
|
1687
1716
|
# Is +uri+ the URI for the current local server?
|
1688
1717
|
def here?(uri)
|
1689
|
-
|
1718
|
+
current_server.here?(uri) rescue false
|
1719
|
+
# (current_server.uri rescue nil) == uri
|
1690
1720
|
end
|
1691
1721
|
module_function :here?
|
1692
1722
|
|
@@ -1700,7 +1730,7 @@ module DRb
|
|
1700
1730
|
DRbServer.make_config
|
1701
1731
|
end
|
1702
1732
|
module_function :config
|
1703
|
-
|
1733
|
+
|
1704
1734
|
# Get the front object of the current server.
|
1705
1735
|
#
|
1706
1736
|
# This raises a DRbServerNotFound error if there is no current server.
|
@@ -1736,7 +1766,10 @@ module DRb
|
|
1736
1766
|
end
|
1737
1767
|
module_function :thread
|
1738
1768
|
|
1739
|
-
# Set the default id
|
1769
|
+
# Set the default id conversion object.
|
1770
|
+
#
|
1771
|
+
# This is expected to be an instance such as DRb::DRbIdConv that responds to
|
1772
|
+
# #to_id and #to_obj that can convert objects to and from DRb references.
|
1740
1773
|
#
|
1741
1774
|
# See DRbServer#default_id_conv.
|
1742
1775
|
def install_id_conv(idconv)
|
@@ -1744,7 +1777,7 @@ module DRb
|
|
1744
1777
|
end
|
1745
1778
|
module_function :install_id_conv
|
1746
1779
|
|
1747
|
-
# Set the default acl
|
1780
|
+
# Set the default ACL to +acl+.
|
1748
1781
|
#
|
1749
1782
|
# See DRb::DRbServer.default_acl.
|
1750
1783
|
def install_acl(acl)
|
@@ -1753,12 +1786,24 @@ module DRb
|
|
1753
1786
|
module_function :install_acl
|
1754
1787
|
|
1755
1788
|
@mutex = Mutex.new
|
1756
|
-
def mutex
|
1789
|
+
def mutex # :nodoc:
|
1757
1790
|
@mutex
|
1758
1791
|
end
|
1759
1792
|
module_function :mutex
|
1760
1793
|
|
1761
1794
|
@server = {}
|
1795
|
+
# Registers +server+ with DRb.
|
1796
|
+
#
|
1797
|
+
# This is called when a new DRb::DRbServer is created.
|
1798
|
+
#
|
1799
|
+
# If there is no primary server then +server+ becomes the primary server.
|
1800
|
+
#
|
1801
|
+
# Example:
|
1802
|
+
#
|
1803
|
+
# require 'drb'
|
1804
|
+
#
|
1805
|
+
# s = DRb::DRbServer.new # automatically calls regist_server
|
1806
|
+
# DRb.fetch_server s.uri #=> #<DRb::DRbServer:0x...>
|
1762
1807
|
def regist_server(server)
|
1763
1808
|
@server[server.uri] = server
|
1764
1809
|
mutex.synchronize do
|
@@ -1767,17 +1812,22 @@ module DRb
|
|
1767
1812
|
end
|
1768
1813
|
module_function :regist_server
|
1769
1814
|
|
1815
|
+
# Removes +server+ from the list of registered servers.
|
1770
1816
|
def remove_server(server)
|
1771
1817
|
@server.delete(server.uri)
|
1772
1818
|
end
|
1773
1819
|
module_function :remove_server
|
1774
|
-
|
1820
|
+
|
1821
|
+
# Retrieves the server with the given +uri+.
|
1822
|
+
#
|
1823
|
+
# See also regist_server and remove_server.
|
1775
1824
|
def fetch_server(uri)
|
1776
1825
|
@server[uri]
|
1777
1826
|
end
|
1778
1827
|
module_function :fetch_server
|
1779
1828
|
end
|
1780
1829
|
|
1830
|
+
# :stopdoc:
|
1781
1831
|
DRbObject = DRb::DRbObject
|
1782
1832
|
DRbUndumped = DRb::DRbUndumped
|
1783
1833
|
DRbIdConv = DRb::DRbIdConv
|