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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cd45867e7eb55a838219dc718a431d9214b7b00a
4
- data.tar.gz: dae31b966a9a8f731ef99dc661aa8b4a30007c67
3
+ metadata.gz: 213ea322bd994875b60a34c5757494df17eff965
4
+ data.tar.gz: d65733cb1206a3f02b1c2fc0da9ce5bfdc33c0c3
5
5
  SHA512:
6
- metadata.gz: e3347bd1ee0152ffb00cd9377f3084d1deecc716ea39edc679b2a6525844aafd10e0398247ab837e59d8336f0d185e5fba046c38d8233cb3d84e66d47055d1b6
7
- data.tar.gz: 1a3439c7c928ded5c29ee8fced65a15b5edbe42a54a94df423cfcb1c38923a99f0bee1fd84d4edf952b9737e90454951844e64655094097442369d351f1ae9ec
6
+ metadata.gz: ce34af436338b849c3645ed0b9a5ad5726741881d5c5ee15b3c611b340129b605649a518a90d2cfdc2e1e608fcaa38601e6659d6abe13a3ebd8ff9639d08a6bb
7
+ data.tar.gz: 4174c5e60f34958c2cb6d8ab287e82ff7a55aa7bd30327de311f242cc6170157c53318ae23e1e4330b0a36359bc1afdf0435487c85de398a2b09c06e23a0032b
@@ -1,8 +1,9 @@
1
1
  language: ruby
2
2
  before_install:
3
+ - rvm use $RVM --install --binary --fuzzy
3
4
  - gem update --system
4
5
  - gem --version
5
6
  - gem install rubysl-bundler
7
+ env:
8
+ - RVM=rbx-nightly-d21 RUBYLIB=lib
6
9
  script: bundle exec mspec spec
7
- rvm:
8
- - rbx-nightly-18mode
@@ -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
- @pat = [:all]
54
+ @pat = [:all]
16
55
  elsif str.include?('*')
17
56
  @pat = [:name, dot_pat(str)]
18
57
  else
19
- begin
20
- @pat = [:ip, IPAddr.new(str)]
21
- rescue ArgumentError
22
- @pat = [:name, dot_pat(str)]
23
- end
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
- (s == '*') ? '.+' : s
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
- true
96
+ true
46
97
  when :ip
47
- begin
48
- ipaddr = IPAddr.new(addr[3])
49
- ipaddr = ipaddr.ipv4_mapped if @pat[1].ipv6? && ipaddr.ipv4?
50
- rescue ArgumentError
51
- return false
52
- end
53
- (@pat[1].include?(ipaddr)) ? true : false
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
- (@pat[1] =~ addr[2]) ? true : false
106
+ (@pat[1] =~ addr[2]) ? true : false
56
107
  else
57
- false
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
- return true if e.match(addr)
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
- @allow.add(domain)
222
+ @allow.add(domain)
120
223
  when 'deny'
121
- @deny.add(domain)
224
+ @deny.add(domain)
122
225
  else
123
- raise "Invalid ACL entry #{list.to_s}"
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
- allow 192.168.1.1
237
+ allow 192.168.1.1
134
238
  allow ::ffff:192.168.1.2
135
239
  allow 192.168.1.3
136
240
  )
@@ -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://www.chadfowler.com/ruby/drb.html]
38
- # A quick tutorial introduction to using dRuby by Chad Fowler.
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.linux-mag.com/2002-09/ruby_05.html]
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
- @name = $1
465
+ @name = $1
470
466
  when /undefined class\/module (\S+)/
471
- @name = $1
467
+ @name = $1
472
468
  else
473
- @name = nil
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
- Marshal::load(s)
485
+ Marshal::load(s)
490
486
  rescue NameError, ArgumentError
491
- DRbUnknown.new($!, s)
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
- if obj.kind_of? DRbUndumped
518
- DRbObject.new(obj)
519
- else
520
- begin
521
- Marshal.dump(obj)
522
- obj
523
- rescue
524
- DRbObject.new(obj)
525
- end
526
- end
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
- str = Marshal::dump(obj)
562
+ str = Marshal::dump(obj)
558
563
  rescue
559
- str = Marshal::dump(make_proxy(obj, error))
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) # sizeof (N)
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
- ary.push(dump(e))
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 ArgumentError, 'too many arguments' if @argc_limit < argc
621
+ raise(DRbConnError, "too many arguments") if @argc_limit < argc
617
622
  argv = Array.new(argc, nil)
618
623
  argc.times do |n|
619
- argv[n] = load(stream)
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
- begin
731
- return prot.open(uri, config)
732
- rescue DRbBadScheme
733
- rescue DRbConnError
734
- raise($!)
735
- rescue
736
- raise(DRbConnError, "#{uri} - #{$!.inspect}")
737
- end
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
- auto_load(uri, config)
741
- return open(uri, config, false)
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
- begin
759
- return prot.open_server(uri, config)
760
- rescue DRbBadScheme
761
- end
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
- auto_load(uri, config)
765
- return open_server(uri, config, false)
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
- begin
780
- uri, opt = prot.uri_option(uri, config)
781
- # opt = nil if opt == ''
782
- return uri, opt
783
- rescue DRbBadScheme
784
- end
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
- auto_load(uri, config)
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
- require("drb/#{$1}") rescue nil
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
- # Communicates over a TCP socket.
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
- host = $1
810
- port = $2.to_i
811
- option = $4
812
- [host, port, option]
817
+ host = $1
818
+ port = $2.to_i
819
+ option = $4
820
+ [host, port, option]
813
821
  else
814
- raise(DRbBadScheme, uri) unless uri =~ /^druby:/
815
- raise(DRbBadURI, 'can\'t parse uri:' + uri)
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 +config+.
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, option = parse_uri(uri)
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
- family = infos.collect { |af, *_| af }.uniq
846
- case family
847
- when ['AF_INET']
848
- return TCPServer.open('0.0.0.0', port)
849
- when ['AF_INET6']
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, opt = parse_uri(uri)
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
- soc = TCPServer.open(host, port)
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
- @socket.close
937
- @socket = nil
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
- s = @socket.accept
947
- break if (@acl ? @acl.allow_socket?(s) : true)
948
- s.close
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
- close
963
- return false
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
- obj = DRb.to_obj(ref)
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('@uri', uri)
1025
- it.instance_variable_set('@ref', ref)
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
- return if uri.nil?
1051
- @uri, option = DRbProtocol.uri_option(uri, DRb.config)
1052
- @ref = DRbURIOption.new(option) unless option.nil?
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
- @uri = uri ? uri : (DRb.uri rescue nil)
1055
- @ref = obj ? DRb.to_id(obj) : nil
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
- obj = DRb.to_obj(@ref)
1087
- DRb.current_server.check_insecure_method(obj, msg_id)
1088
- return obj.__send__(msg_id, *a, &b)
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
- result.set_backtrace(bt + caller)
1120
+ result.set_backtrace(bt + caller)
1104
1121
  raise result
1105
1122
  end
1106
1123
  end
1107
1124
 
1108
- def self.with_friend(uri)
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
- def self.prepare_backtrace(uri, result)
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
- conn = nil
1162
-
1163
- @mutex.synchronize do
1164
- #FIXME
1165
- new_pool = []
1166
- @pool.each do |c|
1167
- if conn.nil? and c.uri == remote_uri
1168
- conn = c if c.alive?
1169
- else
1170
- new_pool.push c
1171
- end
1172
- end
1173
- @pool = new_pool
1174
- end
1175
-
1176
- conn = self.new(remote_uri) unless conn
1177
- succ, result = yield(conn)
1178
- return succ, result
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
- if conn
1182
- if succ
1183
- @mutex.synchronize do
1184
- @pool.unshift(conn)
1185
- @pool.pop.close while @pool.size > POOL_SIZE
1186
- end
1187
- else
1188
- conn.close
1189
- end
1190
- end
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 value for the :acl option.
1270
+ # Set the default access control list to +acl+. The default ACL is +nil+.
1251
1271
  #
1252
- # See #new(). The initial default value is nil.
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
- :idconv => @@idconv,
1283
- :verbose => @@verbose,
1284
- :tcp_acl => @@acl,
1285
- :load_limit => @@load_limit,
1286
- :argc_limit => @@argc_limit,
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
- config = config_or_acl.dup
1363
+ config = config_or_acl.dup
1338
1364
  else
1339
- acl = config_or_acl || @@acl
1340
- config = {
1341
- :tcp_acl => acl
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
- def kill_sub_thread
1421
- Thread.new do
1422
- grp = ThreadGroup.new
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
- begin
1437
- while true
1438
- main_loop
1439
- end
1440
- ensure
1441
- @protocol.close if @protocol
1442
- kill_sub_thread
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.to_s)
1481
- desc = any_to_s(obj)
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.to_s)
1484
- desc = any_to_s(obj)
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
- @drb_server = drb_server
1519
+ @drb_server = drb_server
1495
1520
  @safe_level = drb_server.safe_level
1496
- @client = client
1521
+ @client = client
1497
1522
  end
1498
1523
 
1499
1524
  def perform
1500
- @result = nil
1501
- @succ = false
1502
- setup_message
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
- @succ = true
1527
- if @msg_id == :to_ary && @result.class == Array
1528
- @result = DRbArray.new(@result)
1529
- end
1530
- return @succ, @result
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
- @result = $!
1533
- return @succ, @result
1557
+ @result = $!
1558
+ return @succ, @result
1534
1559
  end
1535
1560
 
1536
1561
  private
1537
1562
  def init_with_client
1538
- obj, msg, argv, block = @client.recv_request
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
- init_with_client
1551
- check_insecure_method
1575
+ init_with_client
1576
+ check_insecure_method
1552
1577
  end
1553
-
1578
+
1554
1579
  def perform_without_block
1555
- if Proc === @obj && @msg_id == :__drb_yield
1580
+ if Proc === @obj && @msg_id == :__drb_yield
1556
1581
  if @argv.size == 1
1557
- ary = @argv
1558
- else
1559
- ary = [@argv]
1560
- end
1561
- ary.collect(&@obj)[0]
1562
- else
1563
- @obj.__send__(@msg_id, *@argv)
1564
- end
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
- @grp.add Thread.current
1591
- Thread.current['DRb'] = { 'client' => client ,
1592
- 'server' => self }
1593
- loop do
1594
- begin
1595
- succ = false
1596
- invoke_method = InvokeMethod.new(self, client)
1597
- succ, result = invoke_method.perform
1598
- if !succ && verbose
1599
- p result
1600
- result.backtrace.each do |x|
1601
- puts x
1602
- end
1603
- end
1604
- client.send_reply(succ, result) rescue nil
1605
- ensure
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
- end
1612
- end
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
- (current_server.uri rescue nil) == uri
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 conv object.
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