rubysl-drb 1.0.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|