ruby-dbus 0.17.0 → 0.18.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/NEWS.md +15 -0
- data/README.md +1 -1
- data/Rakefile +3 -11
- data/VERSION +1 -1
- data/doc/Reference.md +9 -2
- data/examples/doc/_extract_examples +2 -0
- data/examples/gdbus/gdbus +11 -5
- data/examples/no-introspect/nm-test.rb +2 -0
- data/examples/no-introspect/tracker-test.rb +3 -1
- data/examples/rhythmbox/playpause.rb +2 -1
- data/examples/service/call_service.rb +1 -0
- data/examples/service/service_newapi.rb +1 -1
- data/examples/simple/call_introspect.rb +1 -0
- data/examples/simple/get_id.rb +2 -1
- data/examples/simple/properties.rb +2 -0
- data/examples/utils/listnames.rb +1 -0
- data/examples/utils/notify.rb +1 -0
- data/lib/dbus/api_options.rb +9 -0
- data/lib/dbus/auth.rb +12 -7
- data/lib/dbus/bus.rb +114 -70
- data/lib/dbus/bus_name.rb +12 -8
- data/lib/dbus/error.rb +4 -2
- data/lib/dbus/introspect.rb +29 -18
- data/lib/dbus/logger.rb +3 -1
- data/lib/dbus/marshall.rb +118 -86
- data/lib/dbus/matchrule.rb +16 -16
- data/lib/dbus/message.rb +40 -27
- data/lib/dbus/message_queue.rb +10 -5
- data/lib/dbus/object.rb +34 -13
- data/lib/dbus/object_path.rb +9 -5
- data/lib/dbus/proxy_object.rb +18 -4
- data/lib/dbus/proxy_object_factory.rb +11 -7
- data/lib/dbus/proxy_object_interface.rb +26 -22
- data/lib/dbus/type.rb +41 -34
- data/lib/dbus/xml.rb +28 -17
- data/lib/dbus.rb +7 -7
- data/ruby-dbus.gemspec +4 -2
- data/spec/async_spec.rb +2 -0
- data/spec/binding_spec.rb +2 -0
- data/spec/bus_and_xml_backend_spec.rb +2 -0
- data/spec/bus_driver_spec.rb +2 -0
- data/spec/bus_name_spec.rb +3 -1
- data/spec/bus_spec.rb +2 -0
- data/spec/byte_array_spec.rb +2 -0
- data/spec/client_robustness_spec.rb +4 -2
- data/spec/err_msg_spec.rb +2 -0
- data/spec/introspect_xml_parser_spec.rb +2 -0
- data/spec/introspection_spec.rb +2 -0
- data/spec/main_loop_spec.rb +2 -0
- data/spec/node_spec.rb +23 -0
- data/spec/object_path_spec.rb +2 -0
- data/spec/property_spec.rb +11 -2
- data/spec/proxy_object_spec.rb +2 -0
- data/spec/server_robustness_spec.rb +2 -0
- data/spec/server_spec.rb +2 -0
- data/spec/service_newapi.rb +19 -4
- data/spec/session_bus_spec.rb +3 -1
- data/spec/session_bus_spec_manual.rb +2 -0
- data/spec/signal_spec.rb +2 -0
- data/spec/spec_helper.rb +5 -3
- data/spec/thread_safety_spec.rb +2 -0
- data/spec/type_spec.rb +2 -0
- data/spec/value_spec.rb +16 -1
- data/spec/variant_spec.rb +4 -2
- metadata +8 -7
data/lib/dbus/object.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# This file is part of the ruby-dbus project
|
2
4
|
# Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
|
3
5
|
#
|
@@ -6,11 +8,10 @@
|
|
6
8
|
# License, version 2.1 as published by the Free Software Foundation.
|
7
9
|
# See the file "COPYING" for the exact licensing terms.
|
8
10
|
|
9
|
-
require "thread"
|
10
11
|
require_relative "core_ext/class/attribute"
|
11
12
|
|
12
13
|
module DBus
|
13
|
-
PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties"
|
14
|
+
PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties"
|
14
15
|
|
15
16
|
# Exported object type
|
16
17
|
# = Exportable D-Bus object class
|
@@ -20,6 +21,7 @@ module DBus
|
|
20
21
|
class Object
|
21
22
|
# The path of the object.
|
22
23
|
attr_reader :path
|
24
|
+
|
23
25
|
# The interfaces that the object supports. Hash: String => Interface
|
24
26
|
my_class_attribute :intfs
|
25
27
|
self.intfs = {}
|
@@ -43,11 +45,13 @@ module DBus
|
|
43
45
|
when Message::METHOD_CALL
|
44
46
|
reply = nil
|
45
47
|
begin
|
46
|
-
|
48
|
+
iface = intfs[msg.interface]
|
49
|
+
if !iface
|
47
50
|
raise DBus.error("org.freedesktop.DBus.Error.UnknownMethod"),
|
48
51
|
"Interface \"#{msg.interface}\" of object \"#{msg.path}\" doesn't exist"
|
49
52
|
end
|
50
|
-
|
53
|
+
member_sym = msg.member.to_sym
|
54
|
+
meth = iface.methods[member_sym]
|
51
55
|
if !meth
|
52
56
|
raise DBus.error("org.freedesktop.DBus.Error.UnknownMethod"),
|
53
57
|
"Method \"#{msg.member}\" on interface \"#{msg.interface}\" of object \"#{msg.path}\" doesn't exist"
|
@@ -57,11 +61,20 @@ module DBus
|
|
57
61
|
retdata = [*retdata]
|
58
62
|
|
59
63
|
reply = Message.method_return(msg)
|
60
|
-
|
61
|
-
|
64
|
+
if iface.name == PROPERTY_INTERFACE && member_sym == :Get
|
65
|
+
# Use the specific property type instead of the generic variant
|
66
|
+
# returned by Get.
|
67
|
+
# TODO: GetAll and Set still missing
|
68
|
+
property = dbus_lookup_property(msg.params[0], msg.params[1])
|
69
|
+
rsigs = [property.type]
|
70
|
+
else
|
71
|
+
rsigs = meth.rets.map(&:type)
|
72
|
+
end
|
73
|
+
rsigs.zip(retdata).each do |rsig, rdata|
|
74
|
+
reply.add_param(rsig, rdata)
|
62
75
|
end
|
63
|
-
rescue StandardError =>
|
64
|
-
dbus_msg_exc = msg.annotate_exception(
|
76
|
+
rescue StandardError => e
|
77
|
+
dbus_msg_exc = msg.annotate_exception(e)
|
65
78
|
reply = ErrorMessage.from_exception(dbus_msg_exc).reply_to(msg)
|
66
79
|
end
|
67
80
|
@service.bus.message_queue.push(reply)
|
@@ -70,17 +83,19 @@ module DBus
|
|
70
83
|
|
71
84
|
# Select (and create) the interface that the following defined methods
|
72
85
|
# belong to.
|
73
|
-
|
86
|
+
# @param name [String] interface name like "org.example.ManagerManager"
|
87
|
+
# @see https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names-interface
|
88
|
+
def self.dbus_interface(name)
|
74
89
|
@@intfs_mutex.synchronize do
|
75
|
-
@@cur_intf = intfs[
|
90
|
+
@@cur_intf = intfs[name]
|
76
91
|
if !@@cur_intf
|
77
|
-
@@cur_intf = Interface.new(
|
92
|
+
@@cur_intf = Interface.new(name) # validates the name
|
78
93
|
# As this is a mutable class_attr, we cannot use
|
79
|
-
# self.intfs[
|
94
|
+
# self.intfs[name] = @@cur_intf # Hash#[]=
|
80
95
|
# as that would modify parent class attr in place.
|
81
96
|
# Using the setter lets a subclass have the new value
|
82
97
|
# while the superclass keeps the old one.
|
83
|
-
self.intfs = intfs.merge(
|
98
|
+
self.intfs = intfs.merge(name => @@cur_intf)
|
84
99
|
end
|
85
100
|
yield
|
86
101
|
@@cur_intf = nil
|
@@ -110,6 +125,7 @@ module DBus
|
|
110
125
|
# @return [void]
|
111
126
|
def self.dbus_attr_accessor(ruby_name, type, dbus_name: nil)
|
112
127
|
attr_accessor(ruby_name)
|
128
|
+
|
113
129
|
dbus_accessor(ruby_name, type, dbus_name: dbus_name)
|
114
130
|
end
|
115
131
|
|
@@ -129,6 +145,7 @@ module DBus
|
|
129
145
|
# @return (see .dbus_attr_accessor)
|
130
146
|
def self.dbus_attr_reader(ruby_name, type, dbus_name: nil)
|
131
147
|
attr_reader(ruby_name)
|
148
|
+
|
132
149
|
dbus_reader(ruby_name, type, dbus_name: dbus_name)
|
133
150
|
end
|
134
151
|
|
@@ -139,6 +156,7 @@ module DBus
|
|
139
156
|
# @return (see .dbus_attr_accessor)
|
140
157
|
def self.dbus_attr_writer(ruby_name, type, dbus_name: nil)
|
141
158
|
attr_writer(ruby_name)
|
159
|
+
|
142
160
|
dbus_writer(ruby_name, type, dbus_name: dbus_name)
|
143
161
|
end
|
144
162
|
|
@@ -211,6 +229,7 @@ module DBus
|
|
211
229
|
# @return [void]
|
212
230
|
def self.dbus_watcher(ruby_name, dbus_name: nil)
|
213
231
|
raise UndefinedInterface, ruby_name if @@cur_intf.nil?
|
232
|
+
|
214
233
|
cur_intf = @@cur_intf
|
215
234
|
|
216
235
|
ruby_name = ruby_name.to_s.sub(/=$/, "").to_sym
|
@@ -235,6 +254,7 @@ module DBus
|
|
235
254
|
# @param prototype [Prototype]
|
236
255
|
def self.dbus_method(sym, prototype = "", &block)
|
237
256
|
raise UndefinedInterface, sym if @@cur_intf.nil?
|
257
|
+
|
238
258
|
@@cur_intf.define(Method.new(sym.to_s).from_prototype(prototype))
|
239
259
|
|
240
260
|
ruby_name = Object.make_method_name(@@cur_intf.name, sym.to_s)
|
@@ -254,6 +274,7 @@ module DBus
|
|
254
274
|
# Defines a signal for the object with a given name _sym_ and _prototype_.
|
255
275
|
def self.dbus_signal(sym, prototype = "")
|
256
276
|
raise UndefinedInterface, sym if @@cur_intf.nil?
|
277
|
+
|
257
278
|
cur_intf = @@cur_intf
|
258
279
|
signal = Signal.new(sym.to_s).from_prototype(prototype)
|
259
280
|
cur_intf.define(Signal.new(sym.to_s).from_prototype(prototype))
|
data/lib/dbus/object_path.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# This file is part of the ruby-dbus project
|
2
4
|
# Copyright (C) 2019 Martin Vidner
|
3
5
|
#
|
@@ -8,17 +10,19 @@
|
|
8
10
|
|
9
11
|
module DBus
|
10
12
|
# A {::String} that validates at initialization time
|
13
|
+
# @see https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-marshaling-object-path
|
11
14
|
class ObjectPath < String
|
12
15
|
# @raise Error if not a valid object path
|
13
|
-
def initialize(
|
14
|
-
unless self.class.valid?(
|
15
|
-
raise DBus::Error, "Invalid object path #{
|
16
|
+
def initialize(str)
|
17
|
+
unless self.class.valid?(str)
|
18
|
+
raise DBus::Error, "Invalid object path #{str.inspect}"
|
16
19
|
end
|
20
|
+
|
17
21
|
super
|
18
22
|
end
|
19
23
|
|
20
|
-
def self.valid?(
|
21
|
-
|
24
|
+
def self.valid?(str)
|
25
|
+
str == "/" || str =~ %r{\A(/[A-Za-z0-9_]+)+\z}
|
22
26
|
end
|
23
27
|
end
|
24
28
|
end
|
data/lib/dbus/proxy_object.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# This file is part of the ruby-dbus project
|
2
4
|
# Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
|
3
5
|
# Copyright (C) 2009-2014 Martin Vidner
|
@@ -57,6 +59,7 @@ module DBus
|
|
57
59
|
introspect unless introspected
|
58
60
|
ifc = @interfaces[intfname]
|
59
61
|
raise DBus::Error, "no such interface `#{intfname}' on object `#{@path}'" unless ifc
|
62
|
+
|
60
63
|
ifc
|
61
64
|
end
|
62
65
|
|
@@ -93,6 +96,7 @@ module DBus
|
|
93
96
|
# don't overwrite instance methods!
|
94
97
|
next if dup_meths.include?(name)
|
95
98
|
next if self.class.instance_methods.include?(name)
|
99
|
+
|
96
100
|
if univocal_meths.include? name
|
97
101
|
univocal_meths.delete name
|
98
102
|
dup_meths << name
|
@@ -124,14 +128,17 @@ module DBus
|
|
124
128
|
def on_signal(name, &block)
|
125
129
|
# TODO: improve
|
126
130
|
raise NoMethodError unless @default_iface && has_iface?(@default_iface)
|
131
|
+
|
127
132
|
@interfaces[@default_iface].on_signal(name, &block)
|
128
133
|
end
|
129
134
|
|
130
135
|
####################################################
|
131
136
|
private
|
132
137
|
|
133
|
-
# rubocop:disable
|
134
|
-
#
|
138
|
+
# rubocop:disable Lint/MissingSuper
|
139
|
+
# as this should forward everything
|
140
|
+
#
|
141
|
+
# https://github.com/rubocop-hq/ruby-style-guide#no-method-missing
|
135
142
|
# and http://blog.marc-andre.ca/2010/11/15/methodmissing-politely/
|
136
143
|
# have a point to be investigated
|
137
144
|
|
@@ -152,10 +159,17 @@ module DBus
|
|
152
159
|
# interesting, foo.method("unknown")
|
153
160
|
# raises NameError, not NoMethodError
|
154
161
|
raise unless e.to_s =~ /undefined method `#{name}'/
|
162
|
+
|
155
163
|
# BTW e.exception("...") would preserve the class.
|
156
164
|
raise NoMethodError, "undefined method `#{name}' for DBus interface `#{@default_iface}' on object `#{@path}'"
|
157
165
|
end
|
158
166
|
end
|
159
|
-
# rubocop:enable
|
160
|
-
|
167
|
+
# rubocop:enable Lint/MissingSuper
|
168
|
+
|
169
|
+
def respond_to_missing?(name, _include_private = false)
|
170
|
+
@default_iface &&
|
171
|
+
has_iface?(@default_iface) &&
|
172
|
+
@interfaces[@default_iface].methods.key?(name) or super
|
173
|
+
end
|
174
|
+
end
|
161
175
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# This file is part of the ruby-dbus project
|
2
4
|
# Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
|
3
5
|
# Copyright (C) 2009-2014 Martin Vidner
|
@@ -22,17 +24,19 @@ module DBus
|
|
22
24
|
@api = api
|
23
25
|
end
|
24
26
|
|
25
|
-
# Investigates the sub-nodes of the proxy object
|
27
|
+
# Investigates the sub-nodes of the proxy object _pobj_ based on the
|
26
28
|
# introspection XML data _xml_ and sets them up recursively.
|
27
|
-
|
28
|
-
|
29
|
+
# @param pobj [ProxyObject]
|
30
|
+
# @param xml [String]
|
31
|
+
def self.introspect_into(pobj, xml)
|
32
|
+
intfs, pobj.subnodes = IntrospectXMLParser.new(xml).parse
|
29
33
|
intfs.each do |i|
|
30
|
-
poi = ProxyObjectInterface.new(
|
34
|
+
poi = ProxyObjectInterface.new(pobj, i.name)
|
31
35
|
i.methods.each_value { |m| poi.define(m) }
|
32
36
|
i.signals.each_value { |s| poi.define(s) }
|
33
|
-
|
37
|
+
pobj[i.name] = poi
|
34
38
|
end
|
35
|
-
|
39
|
+
pobj.introspected = true
|
36
40
|
end
|
37
41
|
|
38
42
|
# Generates, sets up and returns the proxy object.
|
@@ -41,5 +45,5 @@ module DBus
|
|
41
45
|
ProxyObjectFactory.introspect_into(po, @xml)
|
42
46
|
po
|
43
47
|
end
|
44
|
-
end
|
48
|
+
end
|
45
49
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# This file is part of the ruby-dbus project
|
2
4
|
# Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
|
3
5
|
# Copyright (C) 2009-2014 Martin Vidner
|
@@ -36,27 +38,28 @@ module DBus
|
|
36
38
|
@name
|
37
39
|
end
|
38
40
|
|
39
|
-
# Defines a method on the interface from the Method descriptor
|
40
|
-
|
41
|
-
|
41
|
+
# Defines a method on the interface from the Method descriptor _method_.
|
42
|
+
# @param method [Method]
|
43
|
+
def define_method_from_descriptor(method)
|
44
|
+
method.params.each do |fpar|
|
42
45
|
par = fpar.type
|
43
46
|
# This is the signature validity check
|
44
47
|
Type::Parser.new(par).parse
|
45
48
|
end
|
46
49
|
|
47
50
|
singleton_class.class_eval do
|
48
|
-
define_method
|
49
|
-
if
|
50
|
-
raise ArgumentError, "wrong number of arguments (#{args.size} for #{
|
51
|
+
define_method method.name do |*args, &reply_handler|
|
52
|
+
if method.params.size != args.size
|
53
|
+
raise ArgumentError, "wrong number of arguments (#{args.size} for #{method.params.size})"
|
51
54
|
end
|
52
55
|
|
53
56
|
msg = Message.new(Message::METHOD_CALL)
|
54
57
|
msg.path = @object.path
|
55
58
|
msg.interface = @name
|
56
59
|
msg.destination = @object.destination
|
57
|
-
msg.member =
|
60
|
+
msg.member = method.name
|
58
61
|
msg.sender = @object.bus.unique_name
|
59
|
-
|
62
|
+
method.params.each do |fpar|
|
60
63
|
par = fpar.type
|
61
64
|
msg.add_param(par, args.shift)
|
62
65
|
end
|
@@ -64,30 +67,31 @@ module DBus
|
|
64
67
|
if ret.nil? || @object.api.proxy_method_returns_array
|
65
68
|
ret
|
66
69
|
else
|
67
|
-
|
70
|
+
method.rets.size == 1 ? ret.first : ret
|
68
71
|
end
|
69
72
|
end
|
70
73
|
end
|
71
74
|
|
72
|
-
@methods[
|
75
|
+
@methods[method.name] = method
|
73
76
|
end
|
74
77
|
|
75
|
-
# Defines a signal from the descriptor
|
76
|
-
|
77
|
-
|
78
|
+
# Defines a signal from the descriptor _sig_.
|
79
|
+
# @param sig [Signal]
|
80
|
+
def define_signal_from_descriptor(sig)
|
81
|
+
@signals[sig.name] = sig
|
78
82
|
end
|
79
83
|
|
80
|
-
# Defines a signal or method based on the descriptor
|
81
|
-
def define(
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
84
|
+
# Defines a signal or method based on the descriptor _ifc_el_.
|
85
|
+
def define(ifc_el)
|
86
|
+
case ifc_el
|
87
|
+
when Method
|
88
|
+
define_method_from_descriptor(ifc_el)
|
89
|
+
when Signal
|
90
|
+
define_signal_from_descriptor(ifc_el)
|
86
91
|
end
|
87
92
|
end
|
88
93
|
|
89
94
|
# Defines a proxied method on the interface.
|
90
|
-
# Better name: declare_method
|
91
95
|
def define_method(methodname, prototype)
|
92
96
|
m = Method.new(methodname)
|
93
97
|
m.from_prototype(prototype)
|
@@ -110,7 +114,7 @@ module DBus
|
|
110
114
|
end
|
111
115
|
end
|
112
116
|
|
113
|
-
PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties"
|
117
|
+
PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties"
|
114
118
|
|
115
119
|
# Read a property.
|
116
120
|
# @param propname [String]
|
@@ -142,5 +146,5 @@ module DBus
|
|
142
146
|
ret
|
143
147
|
end
|
144
148
|
end
|
145
|
-
end
|
149
|
+
end
|
146
150
|
end
|
data/lib/dbus/type.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# dbus/type.rb - module containing low-level D-Bus data type information
|
2
4
|
#
|
3
5
|
# This file is part of the ruby-dbus project
|
@@ -33,7 +35,7 @@ module DBus
|
|
33
35
|
# protocol.
|
34
36
|
module Type
|
35
37
|
# Mapping from type number to name and alignment.
|
36
|
-
|
38
|
+
TYPE_MAPPING = {
|
37
39
|
0 => ["INVALID", nil],
|
38
40
|
"y" => ["BYTE", 1],
|
39
41
|
"b" => ["BOOLEAN", 4],
|
@@ -54,7 +56,7 @@ module DBus
|
|
54
56
|
"h" => ["UNIX_FD", 4]
|
55
57
|
}.freeze
|
56
58
|
# Defines the set of constants
|
57
|
-
|
59
|
+
TYPE_MAPPING.each_pair do |key, value|
|
58
60
|
Type.const_set(value.first, key)
|
59
61
|
end
|
60
62
|
|
@@ -73,16 +75,17 @@ module DBus
|
|
73
75
|
|
74
76
|
# Create a new type instance for type number _sigtype_.
|
75
77
|
def initialize(sigtype)
|
76
|
-
if !
|
78
|
+
if !TYPE_MAPPING.keys.member?(sigtype)
|
77
79
|
raise SignatureException, "Unknown key in signature: #{sigtype.chr}"
|
78
80
|
end
|
81
|
+
|
79
82
|
@sigtype = sigtype
|
80
83
|
@members = []
|
81
84
|
end
|
82
85
|
|
83
86
|
# Return the required alignment for the type.
|
84
87
|
def alignment
|
85
|
-
|
88
|
+
TYPE_MAPPING[@sigtype].last
|
86
89
|
end
|
87
90
|
|
88
91
|
# Return a string representation of the type according to the
|
@@ -90,36 +93,38 @@ module DBus
|
|
90
93
|
def to_s
|
91
94
|
case @sigtype
|
92
95
|
when STRUCT
|
93
|
-
"(
|
96
|
+
"(#{@members.collect(&:to_s).join})"
|
94
97
|
when ARRAY
|
95
|
-
"a"
|
98
|
+
"a#{child}"
|
96
99
|
when DICT_ENTRY
|
97
|
-
"{
|
100
|
+
"{#{@members.collect(&:to_s).join}}"
|
98
101
|
else
|
99
|
-
if !
|
102
|
+
if !TYPE_MAPPING.keys.member?(@sigtype)
|
100
103
|
raise NotImplementedError
|
101
104
|
end
|
105
|
+
|
102
106
|
@sigtype.chr
|
103
107
|
end
|
104
108
|
end
|
105
109
|
|
106
|
-
# Add a new member type
|
107
|
-
def <<(
|
110
|
+
# Add a new member type _item_.
|
111
|
+
def <<(item)
|
108
112
|
if ![STRUCT, ARRAY, DICT_ENTRY].member?(@sigtype)
|
109
113
|
raise SignatureException
|
110
114
|
end
|
111
115
|
raise SignatureException if @sigtype == ARRAY && !@members.empty?
|
116
|
+
|
112
117
|
if @sigtype == DICT_ENTRY
|
113
|
-
|
118
|
+
case @members.size
|
119
|
+
when 2
|
114
120
|
raise SignatureException, "Dict entries have exactly two members"
|
115
|
-
|
116
|
-
|
117
|
-
if [STRUCT, ARRAY, DICT_ENTRY].member?(a.sigtype)
|
121
|
+
when 0
|
122
|
+
if [STRUCT, ARRAY, DICT_ENTRY].member?(item.sigtype)
|
118
123
|
raise SignatureException, "Dict entry keys must be basic types"
|
119
124
|
end
|
120
125
|
end
|
121
126
|
end
|
122
|
-
@members <<
|
127
|
+
@members << item
|
123
128
|
end
|
124
129
|
|
125
130
|
# Return the first contained member type.
|
@@ -128,19 +133,20 @@ module DBus
|
|
128
133
|
end
|
129
134
|
|
130
135
|
def inspect
|
131
|
-
s =
|
136
|
+
s = TYPE_MAPPING[@sigtype].first
|
132
137
|
if [STRUCT, ARRAY].member?(@sigtype)
|
133
|
-
s += ":
|
138
|
+
s += ": #{@members.inspect}"
|
134
139
|
end
|
135
140
|
s
|
136
141
|
end
|
137
|
-
end
|
142
|
+
end
|
138
143
|
|
139
144
|
# = D-Bus type parser class
|
140
145
|
#
|
141
146
|
# Helper class to parse a type signature in the protocol.
|
142
147
|
class Parser
|
143
148
|
# Create a new parser for the given _signature_.
|
149
|
+
# @param signature [Signature]
|
144
150
|
def initialize(signature)
|
145
151
|
@signature = signature
|
146
152
|
@idx = 0
|
@@ -153,30 +159,31 @@ module DBus
|
|
153
159
|
c
|
154
160
|
end
|
155
161
|
|
156
|
-
# Parse one character
|
157
|
-
def parse_one(
|
162
|
+
# Parse one character _char_ of the signature.
|
163
|
+
def parse_one(char)
|
158
164
|
res = nil
|
159
|
-
case
|
165
|
+
case char
|
160
166
|
when "a"
|
161
167
|
res = Type.new(ARRAY)
|
162
|
-
|
163
|
-
raise SignatureException, "Parse error in #{@signature}" if
|
164
|
-
|
168
|
+
char = nextchar
|
169
|
+
raise SignatureException, "Parse error in #{@signature}" if char.nil?
|
170
|
+
|
171
|
+
child = parse_one(char)
|
165
172
|
res << child
|
166
173
|
when "("
|
167
174
|
res = Type.new(STRUCT)
|
168
|
-
while (
|
169
|
-
res << parse_one(
|
175
|
+
while (char = nextchar) && char != ")"
|
176
|
+
res << parse_one(char)
|
170
177
|
end
|
171
|
-
raise SignatureException, "Parse error in #{@signature}" if
|
178
|
+
raise SignatureException, "Parse error in #{@signature}" if char.nil?
|
172
179
|
when "{"
|
173
180
|
res = Type.new(DICT_ENTRY)
|
174
|
-
while (
|
175
|
-
res << parse_one(
|
181
|
+
while (char = nextchar) && char != "}"
|
182
|
+
res << parse_one(char)
|
176
183
|
end
|
177
|
-
raise SignatureException, "Parse error in #{@signature}" if
|
184
|
+
raise SignatureException, "Parse error in #{@signature}" if char.nil?
|
178
185
|
else
|
179
|
-
res = Type.new(
|
186
|
+
res = Type.new(char)
|
180
187
|
end
|
181
188
|
res
|
182
189
|
end
|
@@ -190,8 +197,8 @@ module DBus
|
|
190
197
|
end
|
191
198
|
ret
|
192
199
|
end
|
193
|
-
end
|
194
|
-
end
|
200
|
+
end
|
201
|
+
end
|
195
202
|
|
196
203
|
# shortcuts
|
197
204
|
|
@@ -206,4 +213,4 @@ module DBus
|
|
206
213
|
[type(string_type), value]
|
207
214
|
end
|
208
215
|
module_function :variant
|
209
|
-
end
|
216
|
+
end
|
data/lib/dbus/xml.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# dbus/xml.rb - introspection parser, rexml/nokogiri abstraction
|
2
4
|
#
|
3
5
|
# This file is part of the ruby-dbus project
|
@@ -26,14 +28,23 @@ module DBus
|
|
26
28
|
attr_accessor :backend
|
27
29
|
end
|
28
30
|
# Creates a new parser for XML data in string _xml_.
|
31
|
+
# @param xml [String]
|
29
32
|
def initialize(xml)
|
30
33
|
@xml = xml
|
31
34
|
end
|
32
35
|
|
33
36
|
class AbstractXML
|
37
|
+
# @!method initialize(xml)
|
38
|
+
# @abstract
|
39
|
+
|
40
|
+
# @!method each(xpath)
|
41
|
+
# @abstract
|
42
|
+
# yields nodes which match xpath of type AbstractXML::Node
|
43
|
+
|
34
44
|
def self.have_nokogiri?
|
35
45
|
Object.const_defined?("Nokogiri")
|
36
46
|
end
|
47
|
+
|
37
48
|
class Node
|
38
49
|
def initialize(node)
|
39
50
|
@node = node
|
@@ -46,12 +57,6 @@ module DBus
|
|
46
57
|
# yields child nodes which match xpath of type AbstractXML::Node
|
47
58
|
def each(xpath); end
|
48
59
|
end
|
49
|
-
# required methods
|
50
|
-
# initialize parser with xml string
|
51
|
-
def initialize(xml); end
|
52
|
-
|
53
|
-
# yields nodes which match xpath of type AbstractXML::Node
|
54
|
-
def each(xpath); end
|
55
60
|
end
|
56
61
|
|
57
62
|
class NokogiriParser < AbstractXML
|
@@ -64,7 +69,9 @@ module DBus
|
|
64
69
|
@node.search(path).each { |node| block.call NokogiriNode.new(node) }
|
65
70
|
end
|
66
71
|
end
|
72
|
+
|
67
73
|
def initialize(xml)
|
74
|
+
super()
|
68
75
|
@doc = Nokogiri.XML(xml)
|
69
76
|
end
|
70
77
|
|
@@ -83,7 +90,9 @@ module DBus
|
|
83
90
|
@node.elements.each(path) { |node| block.call REXMLNode.new(node) }
|
84
91
|
end
|
85
92
|
end
|
93
|
+
|
86
94
|
def initialize(xml)
|
95
|
+
super()
|
87
96
|
@doc = REXML::Document.new(xml)
|
88
97
|
end
|
89
98
|
|
@@ -136,28 +145,30 @@ module DBus
|
|
136
145
|
######################################################################
|
137
146
|
private
|
138
147
|
|
139
|
-
# Parses a method signature XML element
|
140
|
-
# method/signal
|
141
|
-
|
142
|
-
|
148
|
+
# Parses a method signature XML element *elem* and initialises
|
149
|
+
# method/signal *methsig*.
|
150
|
+
# @param elem [AbstractXML::Node]
|
151
|
+
def parse_methsig(elem, methsig)
|
152
|
+
elem.each("arg") do |ae|
|
143
153
|
name = ae["name"]
|
144
154
|
dir = ae["direction"]
|
145
155
|
sig = ae["type"]
|
146
|
-
|
156
|
+
case methsig
|
157
|
+
when DBus::Signal
|
147
158
|
# Direction can only be "out", ignore it
|
148
|
-
|
149
|
-
|
159
|
+
methsig.add_fparam(name, sig)
|
160
|
+
when DBus::Method
|
150
161
|
case dir
|
151
162
|
# This is a method, so dir defaults to "in"
|
152
163
|
when "in", nil
|
153
|
-
|
164
|
+
methsig.add_fparam(name, sig)
|
154
165
|
when "out"
|
155
|
-
|
166
|
+
methsig.add_return(name, sig)
|
156
167
|
end
|
157
168
|
else
|
158
169
|
raise NotImplementedError, dir
|
159
170
|
end
|
160
171
|
end
|
161
172
|
end
|
162
|
-
end
|
163
|
-
end
|
173
|
+
end
|
174
|
+
end
|
data/lib/dbus.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# dbus.rb - Module containing the low-level D-Bus implementation
|
2
4
|
#
|
3
5
|
# This file is part of the ruby-dbus project
|
@@ -28,22 +30,20 @@ require_relative "dbus/type"
|
|
28
30
|
require_relative "dbus/xml"
|
29
31
|
|
30
32
|
require "socket"
|
31
|
-
require "thread"
|
32
|
-
|
33
33
|
# = D-Bus main module
|
34
34
|
#
|
35
35
|
# Module containing all the D-Bus modules and classes.
|
36
36
|
module DBus
|
37
37
|
# Default socket name for the system bus.
|
38
|
-
|
38
|
+
SYSTEM_BUS_ADDRESS = "unix:path=/var/run/dbus/system_bus_socket"
|
39
39
|
|
40
40
|
# Byte signifying big endianness.
|
41
|
-
BIG_END = "B"
|
41
|
+
BIG_END = "B"
|
42
42
|
# Byte signifying little endianness.
|
43
|
-
LIL_END = "l"
|
43
|
+
LIL_END = "l"
|
44
44
|
|
45
45
|
# Byte signifying the host's endianness.
|
46
|
-
HOST_END = if [0x01020304].pack("L").
|
46
|
+
HOST_END = if [0x01020304].pack("L").unpack1("V") == 0x01020304
|
47
47
|
LIL_END
|
48
48
|
else
|
49
49
|
BIG_END
|
@@ -69,4 +69,4 @@ module DBus
|
|
69
69
|
# Exception raised when invalid introspection data is parsed/used.
|
70
70
|
class InvalidIntrospectionData < Exception
|
71
71
|
end
|
72
|
-
end
|
72
|
+
end
|