ruby-dbus 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/NEWS +8 -0
- data/README.md +41 -4
- data/Rakefile +15 -16
- data/VERSION +1 -1
- data/lib/dbus.rb +18 -14
- data/lib/dbus/bus.rb +32 -168
- data/lib/dbus/error.rb +4 -2
- data/lib/dbus/export.rb +3 -2
- data/lib/dbus/introspect.rb +0 -294
- data/lib/dbus/marshall.rb +1 -1
- data/lib/dbus/message.rb +8 -0
- data/lib/dbus/message_queue.rb +166 -0
- data/lib/dbus/proxy_object.rb +149 -0
- data/lib/dbus/proxy_object_factory.rb +41 -0
- data/lib/dbus/proxy_object_interface.rb +128 -0
- data/ruby-dbus.gemspec +1 -0
- data/test/{async_test.rb → async_spec.rb} +10 -11
- data/test/{binding_test.rb → binding_spec.rb} +23 -25
- data/test/bus_and_xml_backend_spec.rb +39 -0
- data/test/bus_driver_spec.rb +20 -0
- data/test/{bus_test.rb → bus_spec.rb} +8 -7
- data/test/byte_array_spec.rb +38 -0
- data/test/err_msg_spec.rb +42 -0
- data/test/{introspect_xml_parser_test.rb → introspect_xml_parser_spec.rb} +5 -6
- data/test/introspection_spec.rb +32 -0
- data/test/{main_loop_test.rb → main_loop_spec.rb} +10 -7
- data/test/property_spec.rb +53 -0
- data/test/server_robustness_spec.rb +66 -0
- data/test/{server_test.rb → server_spec.rb} +10 -11
- data/test/service_newapi.rb +1 -1
- data/test/session_bus_spec_manual.rb +15 -0
- data/test/{signal_test.rb → signal_spec.rb} +13 -14
- data/test/spec_helper.rb +33 -0
- data/test/{thread_safety_test.rb → thread_safety_spec.rb} +5 -6
- data/test/type_spec.rb +19 -0
- data/test/{value_test.rb → value_spec.rb} +23 -24
- data/test/variant_spec.rb +66 -0
- metadata +40 -22
- data/test/bus_and_xml_backend_test.rb +0 -43
- data/test/bus_driver_test.rb +0 -19
- data/test/byte_array_test.rb +0 -42
- data/test/err_msg_test.rb +0 -59
- data/test/introspection_test.rb +0 -32
- data/test/property_test.rb +0 -65
- data/test/server_robustness_test.rb +0 -73
- data/test/session_bus_test_manual.rb +0 -17
- data/test/test_helper.rb +0 -14
- data/test/type_test.rb +0 -23
- data/test/variant_test.rb +0 -67
data/lib/dbus/error.rb
CHANGED
@@ -34,8 +34,10 @@ module DBus
|
|
34
34
|
end
|
35
35
|
end # class Error
|
36
36
|
|
37
|
-
# raise
|
38
|
-
#
|
37
|
+
# @example raise a generic error
|
38
|
+
# raise DBus.error, "message"
|
39
|
+
# @example raise a specific error
|
40
|
+
# raise DBus.error("org.example.Error.SeatOccupied"), "Seat #{n} is occupied"
|
39
41
|
def error(name = "org.freedesktop.DBus.Error.Failed")
|
40
42
|
# message will be set by Kernel.raise
|
41
43
|
DBus::Error.new(nil, name)
|
data/lib/dbus/export.rb
CHANGED
@@ -64,9 +64,10 @@ module DBus
|
|
64
64
|
reply.add_param(rsig.type, rdata)
|
65
65
|
end
|
66
66
|
rescue => ex
|
67
|
-
|
67
|
+
dbus_msg_exc = msg.annotate_exception(ex)
|
68
|
+
reply = ErrorMessage.from_exception(dbus_msg_exc).reply_to(msg)
|
68
69
|
end
|
69
|
-
@service.bus.
|
70
|
+
@service.bus.message_queue.push(reply)
|
70
71
|
end
|
71
72
|
end
|
72
73
|
|
data/lib/dbus/introspect.rb
CHANGED
@@ -215,299 +215,5 @@ module DBus
|
|
215
215
|
xml
|
216
216
|
end
|
217
217
|
end # class Signal
|
218
|
-
|
219
|
-
# = D-Bus proxy object interface class
|
220
|
-
#
|
221
|
-
# A class similar to the normal Interface used as a proxy for remote
|
222
|
-
# object interfaces.
|
223
|
-
class ProxyObjectInterface
|
224
|
-
# The proxied methods contained in the interface.
|
225
|
-
attr_accessor :methods
|
226
|
-
# The proxied signals contained in the interface.
|
227
|
-
attr_accessor :signals
|
228
|
-
# The proxy object to which this interface belongs.
|
229
|
-
attr_reader :object
|
230
|
-
# The name of the interface.
|
231
|
-
attr_reader :name
|
232
|
-
|
233
|
-
# Creates a new proxy interface for the given proxy _object_
|
234
|
-
# and the given _name_.
|
235
|
-
def initialize(object, name)
|
236
|
-
@object, @name = object, name
|
237
|
-
@methods, @signals = Hash.new, Hash.new
|
238
|
-
end
|
239
|
-
|
240
|
-
# Returns the string representation of the interface (the name).
|
241
|
-
def to_str
|
242
|
-
@name
|
243
|
-
end
|
244
|
-
|
245
|
-
# Returns the singleton class of the interface.
|
246
|
-
def singleton_class
|
247
|
-
(class << self ; self ; end)
|
248
|
-
end
|
249
|
-
|
250
|
-
# Defines a method on the interface from the Method descriptor _m_.
|
251
|
-
def define_method_from_descriptor(m)
|
252
|
-
m.params.each do |fpar|
|
253
|
-
par = fpar.type
|
254
|
-
# This is the signature validity check
|
255
|
-
Type::Parser.new(par).parse
|
256
|
-
end
|
257
|
-
|
258
|
-
singleton_class.class_eval do
|
259
|
-
define_method m.name do |*args, &reply_handler|
|
260
|
-
if m.params.size != args.size
|
261
|
-
raise ArgumentError, "wrong number of arguments (#{args.size} for #{m.params.size})"
|
262
|
-
end
|
263
|
-
|
264
|
-
msg = Message.new(Message::METHOD_CALL)
|
265
|
-
msg.path = @object.path
|
266
|
-
msg.interface = @name
|
267
|
-
msg.destination = @object.destination
|
268
|
-
msg.member = m.name
|
269
|
-
msg.sender = @object.bus.unique_name
|
270
|
-
m.params.each do |fpar|
|
271
|
-
par = fpar.type
|
272
|
-
msg.add_param(par, args.shift)
|
273
|
-
end
|
274
|
-
@object.bus.send_sync_or_async(msg, &reply_handler)
|
275
|
-
end
|
276
|
-
end
|
277
|
-
|
278
|
-
@methods[m.name] = m
|
279
|
-
end
|
280
|
-
|
281
|
-
# Defines a signal from the descriptor _s_.
|
282
|
-
def define_signal_from_descriptor(s)
|
283
|
-
@signals[s.name] = s
|
284
|
-
end
|
285
|
-
|
286
|
-
# Defines a signal or method based on the descriptor _m_.
|
287
|
-
def define(m)
|
288
|
-
if m.kind_of?(Method)
|
289
|
-
define_method_from_descriptor(m)
|
290
|
-
elsif m.kind_of?(Signal)
|
291
|
-
define_signal_from_descriptor(m)
|
292
|
-
end
|
293
|
-
end
|
294
|
-
|
295
|
-
# Defines a proxied method on the interface.
|
296
|
-
def define_method(methodname, prototype)
|
297
|
-
m = Method.new(methodname)
|
298
|
-
m.from_prototype(prototype)
|
299
|
-
define(m)
|
300
|
-
end
|
301
|
-
|
302
|
-
# @overload on_signal(name, &block)
|
303
|
-
# @overload on_signal(bus, name, &block)
|
304
|
-
# Registers a handler (code block) for a signal with _name_ arriving
|
305
|
-
# over the given _bus_. If no block is given, the signal is unregistered.
|
306
|
-
# Note that specifying _bus_ is discouraged and the option is kept only for
|
307
|
-
# backward compatibility.
|
308
|
-
# @return [void]
|
309
|
-
def on_signal(bus = @object.bus, name, &block)
|
310
|
-
mr = DBus::MatchRule.new.from_signal(self, name)
|
311
|
-
if block.nil?
|
312
|
-
bus.remove_match(mr)
|
313
|
-
else
|
314
|
-
bus.add_match(mr) { |msg| block.call(*msg.params) }
|
315
|
-
end
|
316
|
-
end
|
317
|
-
|
318
|
-
PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties"
|
319
|
-
|
320
|
-
# Read a property.
|
321
|
-
def [](propname)
|
322
|
-
self.object[PROPERTY_INTERFACE].Get(self.name, propname)[0]
|
323
|
-
end
|
324
|
-
|
325
|
-
# Write a property.
|
326
|
-
def []=(propname, value)
|
327
|
-
self.object[PROPERTY_INTERFACE].Set(self.name, propname, value)
|
328
|
-
end
|
329
|
-
|
330
|
-
# Read all properties at once, as a hash.
|
331
|
-
# @return [Hash{String}]
|
332
|
-
def all_properties
|
333
|
-
self.object[PROPERTY_INTERFACE].GetAll(self.name)[0]
|
334
|
-
end
|
335
|
-
end # class ProxyObjectInterface
|
336
|
-
|
337
|
-
# D-Bus proxy object class
|
338
|
-
#
|
339
|
-
# Class representing a remote object in an external application.
|
340
|
-
# Typically, calling a method on an instance of a ProxyObject sends a message
|
341
|
-
# over the bus so that the method is executed remotely on the correctponding
|
342
|
-
# object.
|
343
|
-
class ProxyObject
|
344
|
-
# The names of direct subnodes of the object in the tree.
|
345
|
-
attr_accessor :subnodes
|
346
|
-
# Flag determining whether the object has been introspected.
|
347
|
-
attr_accessor :introspected
|
348
|
-
# The (remote) destination of the object.
|
349
|
-
attr_reader :destination
|
350
|
-
# The path to the object.
|
351
|
-
attr_reader :path
|
352
|
-
# The bus the object is reachable via.
|
353
|
-
attr_reader :bus
|
354
|
-
# @return [String] The name of the default interface of the object.
|
355
|
-
attr_accessor :default_iface
|
356
|
-
|
357
|
-
# Creates a new proxy object living on the given _bus_ at destination _dest_
|
358
|
-
# on the given _path_.
|
359
|
-
def initialize(bus, dest, path)
|
360
|
-
@bus, @destination, @path = bus, dest, path
|
361
|
-
@interfaces = Hash.new
|
362
|
-
@subnodes = Array.new
|
363
|
-
end
|
364
|
-
|
365
|
-
# Returns the interfaces of the object.
|
366
|
-
def interfaces
|
367
|
-
@interfaces.keys
|
368
|
-
end
|
369
|
-
|
370
|
-
# Retrieves an interface of the proxy object
|
371
|
-
# @param [String] intfname
|
372
|
-
# @return [ProxyObjectInterface]
|
373
|
-
def [](intfname)
|
374
|
-
@interfaces[intfname]
|
375
|
-
end
|
376
|
-
|
377
|
-
# Maps the given interface name _intfname_ to the given interface _intf.
|
378
|
-
# @param [String] intfname
|
379
|
-
# @param [ProxyObjectInterface] intf
|
380
|
-
# @return [ProxyObjectInterface]
|
381
|
-
def []=(intfname, intf)
|
382
|
-
@interfaces[intfname] = intf
|
383
|
-
end
|
384
|
-
|
385
|
-
# Introspects the remote object. Allows you to find and select
|
386
|
-
# interfaces on the object.
|
387
|
-
def introspect
|
388
|
-
# Synchronous call here.
|
389
|
-
xml = @bus.introspect_data(@destination, @path)
|
390
|
-
ProxyObjectFactory.introspect_into(self, xml)
|
391
|
-
define_shortcut_methods()
|
392
|
-
xml
|
393
|
-
end
|
394
|
-
|
395
|
-
# For each non duplicated method name in any interface present on the
|
396
|
-
# caller, defines a shortcut method dynamically.
|
397
|
-
# This function is automatically called when a {ProxyObject} is
|
398
|
-
# introspected.
|
399
|
-
def define_shortcut_methods
|
400
|
-
# builds a list of duplicated methods
|
401
|
-
dup_meths, univocal_meths = [],{}
|
402
|
-
@interfaces.each_value do |intf|
|
403
|
-
intf.methods.each_value do |meth|
|
404
|
-
# Module#instance_methods give us an array of symbols or strings,
|
405
|
-
# depending on which version
|
406
|
-
name = if RUBY_VERSION >= "1.9"
|
407
|
-
meth.name.to_sym
|
408
|
-
else
|
409
|
-
meth.name
|
410
|
-
end
|
411
|
-
# don't overwrite instance methods!
|
412
|
-
if dup_meths.include? name or self.class.instance_methods.include? name
|
413
|
-
next
|
414
|
-
elsif univocal_meths.include? name
|
415
|
-
univocal_meths.delete name
|
416
|
-
dup_meths << name
|
417
|
-
else
|
418
|
-
univocal_meths[name] = intf
|
419
|
-
end
|
420
|
-
end
|
421
|
-
end
|
422
|
-
univocal_meths.each do |name, intf|
|
423
|
-
# creates a shortcut function that forwards each call to the method on
|
424
|
-
# the appropriate intf
|
425
|
-
singleton_class.class_eval do
|
426
|
-
define_method name do |*args, &reply_handler|
|
427
|
-
intf.method(name).call(*args, &reply_handler)
|
428
|
-
end
|
429
|
-
end
|
430
|
-
end
|
431
|
-
end
|
432
|
-
|
433
|
-
# Returns whether the object has an interface with the given _name_.
|
434
|
-
def has_iface?(name)
|
435
|
-
raise "Cannot call has_iface? if not introspected" if not @introspected
|
436
|
-
@interfaces.member?(name)
|
437
|
-
end
|
438
|
-
|
439
|
-
# Registers a handler, the code block, for a signal with the given _name_.
|
440
|
-
# It uses _default_iface_ which must have been set.
|
441
|
-
# @return [void]
|
442
|
-
def on_signal(name, &block)
|
443
|
-
if @default_iface and has_iface?(@default_iface)
|
444
|
-
@interfaces[@default_iface].on_signal(name, &block)
|
445
|
-
else
|
446
|
-
# TODO improve
|
447
|
-
raise NoMethodError
|
448
|
-
end
|
449
|
-
end
|
450
|
-
|
451
|
-
####################################################
|
452
|
-
private
|
453
|
-
|
454
|
-
# Handles all unkown methods, mostly to route method calls to the
|
455
|
-
# default interface.
|
456
|
-
def method_missing(name, *args, &reply_handler)
|
457
|
-
if @default_iface and has_iface?(@default_iface)
|
458
|
-
begin
|
459
|
-
@interfaces[@default_iface].method(name).call(*args, &reply_handler)
|
460
|
-
rescue NameError => e
|
461
|
-
# interesting, foo.method("unknown")
|
462
|
-
# raises NameError, not NoMethodError
|
463
|
-
raise unless e.to_s =~ /undefined method `#{name}'/
|
464
|
-
# BTW e.exception("...") would preserve the class.
|
465
|
-
raise NoMethodError,"undefined method `#{name}' for DBus interface `#{@default_iface}' on object `#{@path}'"
|
466
|
-
end
|
467
|
-
else
|
468
|
-
# TODO distinguish:
|
469
|
-
# - di not specified
|
470
|
-
#TODO
|
471
|
-
# - di is specified but not found in introspection data
|
472
|
-
raise NoMethodError, "undefined method `#{name}' for DBus interface `#{@default_iface}' on object `#{@path}'"
|
473
|
-
end
|
474
|
-
end
|
475
|
-
|
476
|
-
# Returns the singleton class of the object.
|
477
|
-
def singleton_class
|
478
|
-
(class << self ; self ; end)
|
479
|
-
end
|
480
|
-
end # class ProxyObject
|
481
|
-
|
482
|
-
# = D-Bus proxy object factory class
|
483
|
-
#
|
484
|
-
# Class that generates and sets up a proxy object based on introspection data.
|
485
|
-
class ProxyObjectFactory
|
486
|
-
# Creates a new proxy object factory for the given introspection XML _xml_,
|
487
|
-
# _bus_, destination _dest_, and _path_.
|
488
|
-
def initialize(xml, bus, dest, path)
|
489
|
-
@xml, @bus, @path, @dest = xml, bus, path, dest
|
490
|
-
end
|
491
|
-
|
492
|
-
# Investigates the sub-nodes of the proxy object _po_ based on the
|
493
|
-
# introspection XML data _xml_ and sets them up recursively.
|
494
|
-
def ProxyObjectFactory.introspect_into(po, xml)
|
495
|
-
intfs, po.subnodes = IntrospectXMLParser.new(xml).parse
|
496
|
-
intfs.each do |i|
|
497
|
-
poi = ProxyObjectInterface.new(po, i.name)
|
498
|
-
i.methods.each_value { |m| poi.define(m) }
|
499
|
-
i.signals.each_value { |s| poi.define(s) }
|
500
|
-
po[i.name] = poi
|
501
|
-
end
|
502
|
-
po.introspected = true
|
503
|
-
end
|
504
|
-
|
505
|
-
# Generates, sets up and returns the proxy object.
|
506
|
-
def build
|
507
|
-
po = ProxyObject.new(@bus, @dest, @path)
|
508
|
-
ProxyObjectFactory.introspect_into(po, @xml)
|
509
|
-
po
|
510
|
-
end
|
511
|
-
end # class ProxyObjectFactory
|
512
218
|
end # module DBus
|
513
219
|
|
data/lib/dbus/marshall.rb
CHANGED
@@ -212,7 +212,7 @@ module DBus
|
|
212
212
|
packet = get_string
|
213
213
|
when Type::STRING
|
214
214
|
packet = get_string
|
215
|
-
packet.force_encoding('UTF-8')
|
215
|
+
packet.force_encoding('UTF-8')
|
216
216
|
when Type::SIGNATURE
|
217
217
|
packet = get_signature
|
218
218
|
when Type::DICT_ENTRY
|
data/lib/dbus/message.rb
CHANGED
@@ -235,6 +235,14 @@ module DBus
|
|
235
235
|
ret, _ = unmarshall_buffer(buf)
|
236
236
|
ret
|
237
237
|
end
|
238
|
+
|
239
|
+
# Make a new exception from ex, mark it as being caused by this message
|
240
|
+
# @api private
|
241
|
+
def annotate_exception(ex)
|
242
|
+
new_ex = ex.exception("#{ex}; caused by #{self}")
|
243
|
+
new_ex.set_backtrace(ex.backtrace)
|
244
|
+
new_ex
|
245
|
+
end
|
238
246
|
end # class Message
|
239
247
|
|
240
248
|
class MethodReturnMessage < Message
|
@@ -0,0 +1,166 @@
|
|
1
|
+
# This file is part of the ruby-dbus project
|
2
|
+
# Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
|
3
|
+
# Copyright (C) 2009-2014 Martin Vidner
|
4
|
+
#
|
5
|
+
# This library is free software; you can redistribute it and/or
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
7
|
+
# License, version 2.1 as published by the Free Software Foundation.
|
8
|
+
# See the file "COPYING" for the exact licensing terms.
|
9
|
+
|
10
|
+
require "fcntl"
|
11
|
+
require "socket"
|
12
|
+
|
13
|
+
module DBus
|
14
|
+
class MessageQueue
|
15
|
+
# The socket that is used to connect with the bus.
|
16
|
+
attr_reader :socket
|
17
|
+
|
18
|
+
def initialize(address)
|
19
|
+
@address = address
|
20
|
+
@buffer = ""
|
21
|
+
@is_tcp = false
|
22
|
+
connect
|
23
|
+
end
|
24
|
+
|
25
|
+
# TODO failure modes
|
26
|
+
#
|
27
|
+
# If _non_block_ is true, return nil instead of waiting
|
28
|
+
# EOFError may be raised
|
29
|
+
def pop(non_block = false)
|
30
|
+
buffer_from_socket_nonblock
|
31
|
+
message = message_from_buffer_nonblock
|
32
|
+
unless non_block
|
33
|
+
# we can block
|
34
|
+
while message.nil?
|
35
|
+
r, d, d = IO.select([@socket])
|
36
|
+
if r and r[0] == @socket
|
37
|
+
buffer_from_socket_nonblock
|
38
|
+
message = message_from_buffer_nonblock
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
message
|
43
|
+
end
|
44
|
+
|
45
|
+
def push(message)
|
46
|
+
@socket.write(message.marshall)
|
47
|
+
end
|
48
|
+
alias :<< :push
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
# Connect to the bus and initialize the connection.
|
53
|
+
def connect
|
54
|
+
addresses = @address.split ";"
|
55
|
+
# connect to first one that succeeds
|
56
|
+
worked = addresses.find do |a|
|
57
|
+
transport, keyvaluestring = a.split ":"
|
58
|
+
kv_list = keyvaluestring.split ","
|
59
|
+
kv_hash = Hash.new
|
60
|
+
kv_list.each do |kv|
|
61
|
+
key, escaped_value = kv.split "="
|
62
|
+
value = escaped_value.gsub(/%(..)/) {|m| [$1].pack "H2" }
|
63
|
+
kv_hash[key] = value
|
64
|
+
end
|
65
|
+
case transport
|
66
|
+
when "unix"
|
67
|
+
connect_to_unix kv_hash
|
68
|
+
when "tcp"
|
69
|
+
connect_to_tcp kv_hash
|
70
|
+
when "launchd"
|
71
|
+
connect_to_launchd kv_hash
|
72
|
+
else
|
73
|
+
# ignore, report?
|
74
|
+
end
|
75
|
+
end
|
76
|
+
worked
|
77
|
+
# returns the address that worked or nil.
|
78
|
+
# how to report failure?
|
79
|
+
end
|
80
|
+
|
81
|
+
# Connect to a bus over tcp and initialize the connection.
|
82
|
+
def connect_to_tcp(params)
|
83
|
+
#check if the path is sufficient
|
84
|
+
if params.key?("host") and params.key?("port")
|
85
|
+
begin
|
86
|
+
#initialize the tcp socket
|
87
|
+
@socket = TCPSocket.new(params["host"],params["port"].to_i)
|
88
|
+
@socket.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
89
|
+
init_connection
|
90
|
+
@is_tcp = true
|
91
|
+
rescue Exception => e
|
92
|
+
puts "Oops:", e
|
93
|
+
puts "Error: Could not establish connection to: #{@path}, will now exit."
|
94
|
+
exit(1) #a little harsh
|
95
|
+
end
|
96
|
+
else
|
97
|
+
#Danger, Will Robinson: the specified "path" is not usable
|
98
|
+
puts "Error: supplied path: #{@path}, unusable! sorry."
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# Connect to an abstract unix bus and initialize the connection.
|
103
|
+
def connect_to_unix(params)
|
104
|
+
@socket = Socket.new(Socket::Constants::PF_UNIX,Socket::Constants::SOCK_STREAM, 0)
|
105
|
+
@socket.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
106
|
+
if ! params['abstract'].nil?
|
107
|
+
if HOST_END == LIL_END
|
108
|
+
sockaddr = "\1\0\0#{params['abstract']}"
|
109
|
+
else
|
110
|
+
sockaddr = "\0\1\0#{params['abstract']}"
|
111
|
+
end
|
112
|
+
elsif ! params['path'].nil?
|
113
|
+
sockaddr = Socket.pack_sockaddr_un(params['path'])
|
114
|
+
end
|
115
|
+
@socket.connect(sockaddr)
|
116
|
+
init_connection
|
117
|
+
end
|
118
|
+
|
119
|
+
def connect_to_launchd(params)
|
120
|
+
socket_var = params['env']
|
121
|
+
socket = `launchctl getenv #{socket_var}`.chomp
|
122
|
+
connect_to_unix 'path' => socket
|
123
|
+
end
|
124
|
+
|
125
|
+
# Initialize the connection to the bus.
|
126
|
+
def init_connection
|
127
|
+
@client = Client.new(@socket)
|
128
|
+
@client.authenticate
|
129
|
+
end
|
130
|
+
|
131
|
+
public # FIXME: fix Main loop instead
|
132
|
+
|
133
|
+
# Get and remove one message from the buffer.
|
134
|
+
# Return the message or nil.
|
135
|
+
def message_from_buffer_nonblock
|
136
|
+
return nil if @buffer.empty?
|
137
|
+
ret = nil
|
138
|
+
begin
|
139
|
+
ret, size = Message.new.unmarshall_buffer(@buffer)
|
140
|
+
@buffer.slice!(0, size)
|
141
|
+
rescue IncompleteBufferException
|
142
|
+
# fall through, let ret be null
|
143
|
+
end
|
144
|
+
ret
|
145
|
+
end
|
146
|
+
|
147
|
+
# The buffer size for messages.
|
148
|
+
MSG_BUF_SIZE = 4096
|
149
|
+
|
150
|
+
# Fill (append) the buffer from data that might be available on the
|
151
|
+
# socket.
|
152
|
+
# EOFError may be raised
|
153
|
+
def buffer_from_socket_nonblock
|
154
|
+
@buffer += @socket.read_nonblock(MSG_BUF_SIZE)
|
155
|
+
rescue EOFError
|
156
|
+
raise # the caller expects it
|
157
|
+
rescue Errno::EAGAIN
|
158
|
+
# fine, would block
|
159
|
+
rescue Exception => e
|
160
|
+
puts "Oops:", e
|
161
|
+
raise if @is_tcp # why?
|
162
|
+
puts "WARNING: read_nonblock failed, falling back to .recv"
|
163
|
+
@buffer += @socket.recv(MSG_BUF_SIZE)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|