ruby-dbus 0.16.0 → 0.18.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/NEWS.md +160 -0
- data/README.md +3 -5
- data/Rakefile +18 -8
- data/VERSION +1 -1
- data/doc/Reference.md +106 -7
- data/examples/doc/_extract_examples +7 -0
- data/examples/gdbus/gdbus +31 -24
- 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 +2 -1
- data/examples/service/complex-property.rb +21 -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 +20 -15
- data/lib/dbus/bus.rb +123 -75
- data/lib/dbus/bus_name.rb +12 -8
- data/lib/dbus/core_ext/class/attribute.rb +1 -1
- data/lib/dbus/data.rb +821 -0
- data/lib/dbus/emits_changed_signal.rb +83 -0
- data/lib/dbus/error.rb +4 -2
- data/lib/dbus/introspect.rb +132 -31
- data/lib/dbus/logger.rb +3 -1
- data/lib/dbus/marshall.rb +247 -296
- data/lib/dbus/matchrule.rb +16 -16
- data/lib/dbus/message.rb +44 -37
- data/lib/dbus/message_queue.rb +16 -10
- data/lib/dbus/object.rb +358 -24
- data/lib/dbus/object_path.rb +11 -6
- data/lib/dbus/proxy_object.rb +22 -1
- data/lib/dbus/proxy_object_factory.rb +13 -7
- data/lib/dbus/proxy_object_interface.rb +63 -30
- data/lib/dbus/raw_message.rb +91 -0
- data/lib/dbus/type.rb +318 -86
- data/lib/dbus/xml.rb +32 -17
- data/lib/dbus.rb +14 -7
- data/ruby-dbus.gemspec +7 -3
- 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/data/marshall.yaml +1667 -0
- data/spec/data_spec.rb +673 -0
- data/spec/emits_changed_signal_spec.rb +58 -0
- 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 +3 -1
- data/spec/node_spec.rb +23 -0
- data/spec/object_path_spec.rb +3 -0
- data/spec/object_spec.rb +138 -0
- data/spec/packet_marshaller_spec.rb +41 -0
- data/spec/packet_unmarshaller_spec.rb +248 -0
- data/spec/property_spec.rb +192 -5
- 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 +70 -70
- data/spec/session_bus_spec.rb +3 -1
- data/spec/session_bus_spec_manual.rb +2 -0
- data/spec/signal_spec.rb +5 -3
- data/spec/spec_helper.rb +37 -9
- data/spec/thread_safety_spec.rb +2 -0
- data/spec/tools/dbus-limited-session.conf +4 -0
- data/spec/type_spec.rb +214 -6
- data/spec/value_spec.rb +16 -1
- data/spec/variant_spec.rb +4 -2
- data/spec/zzz_quit_spec.rb +16 -0
- metadata +34 -8
@@ -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
|
@@ -13,13 +15,16 @@ module DBus
|
|
13
15
|
# A class similar to the normal Interface used as a proxy for remote
|
14
16
|
# object interfaces.
|
15
17
|
class ProxyObjectInterface
|
16
|
-
#
|
17
|
-
|
18
|
-
#
|
19
|
-
|
20
|
-
#
|
18
|
+
# @return [Hash{String => DBus::Method}]
|
19
|
+
attr_reader :methods
|
20
|
+
# @return [Hash{String => Signal}]
|
21
|
+
attr_reader :signals
|
22
|
+
# @return [Hash{Symbol => Property}]
|
23
|
+
attr_reader :properties
|
24
|
+
|
25
|
+
# @return [ProxyObject] The proxy object to which this interface belongs.
|
21
26
|
attr_reader :object
|
22
|
-
# The name of the interface.
|
27
|
+
# @return [String] The name of the interface.
|
23
28
|
attr_reader :name
|
24
29
|
|
25
30
|
# Creates a new proxy interface for the given proxy _object_
|
@@ -29,6 +34,7 @@ module DBus
|
|
29
34
|
@name = name
|
30
35
|
@methods = {}
|
31
36
|
@signals = {}
|
37
|
+
@properties = {}
|
32
38
|
end
|
33
39
|
|
34
40
|
# Returns the string representation of the interface (the name).
|
@@ -36,27 +42,28 @@ module DBus
|
|
36
42
|
@name
|
37
43
|
end
|
38
44
|
|
39
|
-
# Defines a method on the interface from the Method descriptor
|
40
|
-
|
41
|
-
|
45
|
+
# Defines a method on the interface from the Method descriptor _method_.
|
46
|
+
# @param method [Method]
|
47
|
+
def define_method_from_descriptor(method)
|
48
|
+
method.params.each do |fpar|
|
42
49
|
par = fpar.type
|
43
50
|
# This is the signature validity check
|
44
51
|
Type::Parser.new(par).parse
|
45
52
|
end
|
46
53
|
|
47
54
|
singleton_class.class_eval do
|
48
|
-
define_method
|
49
|
-
if
|
50
|
-
raise ArgumentError, "wrong number of arguments (#{args.size} for #{
|
55
|
+
define_method method.name do |*args, &reply_handler|
|
56
|
+
if method.params.size != args.size
|
57
|
+
raise ArgumentError, "wrong number of arguments (#{args.size} for #{method.params.size})"
|
51
58
|
end
|
52
59
|
|
53
60
|
msg = Message.new(Message::METHOD_CALL)
|
54
61
|
msg.path = @object.path
|
55
62
|
msg.interface = @name
|
56
63
|
msg.destination = @object.destination
|
57
|
-
msg.member =
|
64
|
+
msg.member = method.name
|
58
65
|
msg.sender = @object.bus.unique_name
|
59
|
-
|
66
|
+
method.params.each do |fpar|
|
60
67
|
par = fpar.type
|
61
68
|
msg.add_param(par, args.shift)
|
62
69
|
end
|
@@ -64,25 +71,35 @@ module DBus
|
|
64
71
|
if ret.nil? || @object.api.proxy_method_returns_array
|
65
72
|
ret
|
66
73
|
else
|
67
|
-
|
74
|
+
method.rets.size == 1 ? ret.first : ret
|
68
75
|
end
|
69
76
|
end
|
70
77
|
end
|
71
78
|
|
72
|
-
@methods[
|
79
|
+
@methods[method.name] = method
|
73
80
|
end
|
74
81
|
|
75
|
-
# Defines a signal from the descriptor
|
76
|
-
|
77
|
-
|
82
|
+
# Defines a signal from the descriptor _sig_.
|
83
|
+
# @param sig [Signal]
|
84
|
+
def define_signal_from_descriptor(sig)
|
85
|
+
@signals[sig.name] = sig
|
78
86
|
end
|
79
87
|
|
80
|
-
#
|
81
|
-
def
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
88
|
+
# @param prop [Property]
|
89
|
+
def define_property_from_descriptor(prop)
|
90
|
+
@properties[prop.name] = prop
|
91
|
+
end
|
92
|
+
|
93
|
+
# Defines a signal or method based on the descriptor _ifc_el_.
|
94
|
+
# @param ifc_el [DBus::Method,Signal,Property]
|
95
|
+
def define(ifc_el)
|
96
|
+
case ifc_el
|
97
|
+
when Method
|
98
|
+
define_method_from_descriptor(ifc_el)
|
99
|
+
when Signal
|
100
|
+
define_signal_from_descriptor(ifc_el)
|
101
|
+
when Property
|
102
|
+
define_property_from_descriptor(ifc_el)
|
86
103
|
end
|
87
104
|
end
|
88
105
|
|
@@ -109,7 +126,7 @@ module DBus
|
|
109
126
|
end
|
110
127
|
end
|
111
128
|
|
112
|
-
PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties"
|
129
|
+
PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties"
|
113
130
|
|
114
131
|
# Read a property.
|
115
132
|
# @param propname [String]
|
@@ -124,10 +141,26 @@ module DBus
|
|
124
141
|
end
|
125
142
|
|
126
143
|
# Write a property.
|
127
|
-
# @param
|
144
|
+
# @param property_name [String]
|
128
145
|
# @param value [Object]
|
129
|
-
def []=(
|
130
|
-
|
146
|
+
def []=(property_name, value)
|
147
|
+
property = properties[property_name.to_sym]
|
148
|
+
if !property
|
149
|
+
raise DBus.error("org.freedesktop.DBus.Error.UnknownProperty"),
|
150
|
+
"Property '#{name}.#{property_name}' (on object '#{object.path}') not found"
|
151
|
+
end
|
152
|
+
|
153
|
+
case value
|
154
|
+
# accommodate former need to explicitly make a variant with the right type
|
155
|
+
when Data::Variant
|
156
|
+
variant = value
|
157
|
+
else
|
158
|
+
type = property.type
|
159
|
+
typed_value = Data.make_typed(type, value)
|
160
|
+
variant = Data::Variant.new(typed_value, member_type: type)
|
161
|
+
end
|
162
|
+
|
163
|
+
object[PROPERTY_INTERFACE].Set(name, property_name, variant)
|
131
164
|
end
|
132
165
|
|
133
166
|
# Read all properties at once, as a hash.
|
@@ -141,5 +174,5 @@ module DBus
|
|
141
174
|
ret
|
142
175
|
end
|
143
176
|
end
|
144
|
-
end
|
177
|
+
end
|
145
178
|
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This file is part of the ruby-dbus project
|
4
|
+
# Copyright (C) 2022 Martin Vidner
|
5
|
+
#
|
6
|
+
# This library is free software; you can redistribute it and/or
|
7
|
+
# modify it under the terms of the GNU Lesser General Public
|
8
|
+
# License, version 2.1 as published by the Free Software Foundation.
|
9
|
+
# See the file "COPYING" for the exact licensing terms.
|
10
|
+
|
11
|
+
module DBus
|
12
|
+
# A message while it is being parsed: a binary string,
|
13
|
+
# with a position cursor (*pos*), and an *endianness* tag.
|
14
|
+
class RawMessage
|
15
|
+
# @return [String]
|
16
|
+
# attr_reader :bytes
|
17
|
+
|
18
|
+
# @return [Integer] position in the byte buffer
|
19
|
+
attr_reader :pos
|
20
|
+
|
21
|
+
# @return [:little,:big]
|
22
|
+
attr_reader :endianness
|
23
|
+
|
24
|
+
# @param bytes [String]
|
25
|
+
# @param endianness [:little,:big,nil]
|
26
|
+
# if not given, read the 1st byte of *bytes*
|
27
|
+
def initialize(bytes, endianness = nil)
|
28
|
+
@bytes = bytes
|
29
|
+
@pos = 0
|
30
|
+
@endianness = endianness || self.class.endianness(@bytes[0])
|
31
|
+
end
|
32
|
+
|
33
|
+
# Get the endiannes switch as a Symbol,
|
34
|
+
# which will make using it slightly more efficient
|
35
|
+
# @param tag_char [String]
|
36
|
+
# @return [:little,:big]
|
37
|
+
def self.endianness(tag_char)
|
38
|
+
case tag_char
|
39
|
+
when LIL_END
|
40
|
+
:little
|
41
|
+
when BIG_END
|
42
|
+
:big
|
43
|
+
else
|
44
|
+
raise InvalidPacketException, "Incorrect endianness #{tag_char.inspect}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# @return [void]
|
49
|
+
# @raise IncompleteBufferException if there are not enough bytes remaining
|
50
|
+
def want!(size)
|
51
|
+
raise IncompleteBufferException if @pos + size > @bytes.bytesize
|
52
|
+
end
|
53
|
+
|
54
|
+
# @return [String]
|
55
|
+
# @raise IncompleteBufferException if there are not enough bytes remaining
|
56
|
+
# TODO: stress test this with encodings. always binary?
|
57
|
+
def read(size)
|
58
|
+
want!(size)
|
59
|
+
ret = @bytes.slice(@pos, size)
|
60
|
+
@pos += size
|
61
|
+
ret
|
62
|
+
end
|
63
|
+
|
64
|
+
# @return [String]
|
65
|
+
# @api private
|
66
|
+
def remaining_bytes
|
67
|
+
# This returns "" if pos is just past the end of the string,
|
68
|
+
# and nil if it is further.
|
69
|
+
@bytes[@pos..-1]
|
70
|
+
end
|
71
|
+
|
72
|
+
# Align the *pos* index on a multiple of *alignment*
|
73
|
+
# @param alignment [Integer] must be 1, 2, 4 or 8
|
74
|
+
# @return [void]
|
75
|
+
def align(alignment)
|
76
|
+
case alignment
|
77
|
+
when 1
|
78
|
+
nil
|
79
|
+
when 2, 4, 8
|
80
|
+
bits = alignment - 1
|
81
|
+
pad_size = ((@pos + bits) & ~bits) - @pos
|
82
|
+
pad = read(pad_size)
|
83
|
+
unless pad.bytes.all?(&:zero?)
|
84
|
+
raise InvalidPacketException, "Alignment bytes are not NUL"
|
85
|
+
end
|
86
|
+
else
|
87
|
+
raise ArgumentError, "Unsupported alignment #{alignment}"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|