rubysl-drb 1.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml 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