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.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/NEWS.md +160 -0
  3. data/README.md +3 -5
  4. data/Rakefile +18 -8
  5. data/VERSION +1 -1
  6. data/doc/Reference.md +106 -7
  7. data/examples/doc/_extract_examples +7 -0
  8. data/examples/gdbus/gdbus +31 -24
  9. data/examples/no-introspect/nm-test.rb +2 -0
  10. data/examples/no-introspect/tracker-test.rb +3 -1
  11. data/examples/rhythmbox/playpause.rb +2 -1
  12. data/examples/service/call_service.rb +2 -1
  13. data/examples/service/complex-property.rb +21 -0
  14. data/examples/service/service_newapi.rb +1 -1
  15. data/examples/simple/call_introspect.rb +1 -0
  16. data/examples/simple/get_id.rb +2 -1
  17. data/examples/simple/properties.rb +2 -0
  18. data/examples/utils/listnames.rb +1 -0
  19. data/examples/utils/notify.rb +1 -0
  20. data/lib/dbus/api_options.rb +9 -0
  21. data/lib/dbus/auth.rb +20 -15
  22. data/lib/dbus/bus.rb +123 -75
  23. data/lib/dbus/bus_name.rb +12 -8
  24. data/lib/dbus/core_ext/class/attribute.rb +1 -1
  25. data/lib/dbus/data.rb +821 -0
  26. data/lib/dbus/emits_changed_signal.rb +83 -0
  27. data/lib/dbus/error.rb +4 -2
  28. data/lib/dbus/introspect.rb +132 -31
  29. data/lib/dbus/logger.rb +3 -1
  30. data/lib/dbus/marshall.rb +247 -296
  31. data/lib/dbus/matchrule.rb +16 -16
  32. data/lib/dbus/message.rb +44 -37
  33. data/lib/dbus/message_queue.rb +16 -10
  34. data/lib/dbus/object.rb +358 -24
  35. data/lib/dbus/object_path.rb +11 -6
  36. data/lib/dbus/proxy_object.rb +22 -1
  37. data/lib/dbus/proxy_object_factory.rb +13 -7
  38. data/lib/dbus/proxy_object_interface.rb +63 -30
  39. data/lib/dbus/raw_message.rb +91 -0
  40. data/lib/dbus/type.rb +318 -86
  41. data/lib/dbus/xml.rb +32 -17
  42. data/lib/dbus.rb +14 -7
  43. data/ruby-dbus.gemspec +7 -3
  44. data/spec/async_spec.rb +2 -0
  45. data/spec/binding_spec.rb +2 -0
  46. data/spec/bus_and_xml_backend_spec.rb +2 -0
  47. data/spec/bus_driver_spec.rb +2 -0
  48. data/spec/bus_name_spec.rb +3 -1
  49. data/spec/bus_spec.rb +2 -0
  50. data/spec/byte_array_spec.rb +2 -0
  51. data/spec/client_robustness_spec.rb +4 -2
  52. data/spec/data/marshall.yaml +1667 -0
  53. data/spec/data_spec.rb +673 -0
  54. data/spec/emits_changed_signal_spec.rb +58 -0
  55. data/spec/err_msg_spec.rb +2 -0
  56. data/spec/introspect_xml_parser_spec.rb +2 -0
  57. data/spec/introspection_spec.rb +2 -0
  58. data/spec/main_loop_spec.rb +3 -1
  59. data/spec/node_spec.rb +23 -0
  60. data/spec/object_path_spec.rb +3 -0
  61. data/spec/object_spec.rb +138 -0
  62. data/spec/packet_marshaller_spec.rb +41 -0
  63. data/spec/packet_unmarshaller_spec.rb +248 -0
  64. data/spec/property_spec.rb +192 -5
  65. data/spec/proxy_object_spec.rb +2 -0
  66. data/spec/server_robustness_spec.rb +2 -0
  67. data/spec/server_spec.rb +2 -0
  68. data/spec/service_newapi.rb +70 -70
  69. data/spec/session_bus_spec.rb +3 -1
  70. data/spec/session_bus_spec_manual.rb +2 -0
  71. data/spec/signal_spec.rb +5 -3
  72. data/spec/spec_helper.rb +37 -9
  73. data/spec/thread_safety_spec.rb +2 -0
  74. data/spec/tools/dbus-limited-session.conf +4 -0
  75. data/spec/type_spec.rb +214 -6
  76. data/spec/value_spec.rb +16 -1
  77. data/spec/variant_spec.rb +4 -2
  78. data/spec/zzz_quit_spec.rb +16 -0
  79. 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
- # The proxied methods contained in the interface.
17
- attr_accessor :methods
18
- # The proxied signals contained in the interface.
19
- attr_accessor :signals
20
- # The proxy object to which this interface belongs.
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 _m_.
40
- def define_method_from_descriptor(m)
41
- m.params.each do |fpar|
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 m.name do |*args, &reply_handler|
49
- if m.params.size != args.size
50
- raise ArgumentError, "wrong number of arguments (#{args.size} for #{m.params.size})"
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 = m.name
64
+ msg.member = method.name
58
65
  msg.sender = @object.bus.unique_name
59
- m.params.each do |fpar|
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
- m.rets.size == 1 ? ret.first : ret
74
+ method.rets.size == 1 ? ret.first : ret
68
75
  end
69
76
  end
70
77
  end
71
78
 
72
- @methods[m.name] = m
79
+ @methods[method.name] = method
73
80
  end
74
81
 
75
- # Defines a signal from the descriptor _s_.
76
- def define_signal_from_descriptor(s)
77
- @signals[s.name] = s
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
- # Defines a signal or method based on the descriptor _m_.
81
- def define(m)
82
- if m.is_a?(Method)
83
- define_method_from_descriptor(m)
84
- elsif m.is_a?(Signal)
85
- define_signal_from_descriptor(m)
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".freeze
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 propname [String]
144
+ # @param property_name [String]
128
145
  # @param value [Object]
129
- def []=(propname, value)
130
- object[PROPERTY_INTERFACE].Set(name, propname, value)
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 # class ProxyObjectInterface
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