ruby-dbus 0.15.0 → 0.18.0.beta1

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.
Files changed (69) hide show
  1. checksums.yaml +5 -5
  2. data/NEWS.md +41 -1
  3. data/README.md +3 -5
  4. data/Rakefile +18 -8
  5. data/VERSION +1 -1
  6. data/doc/Reference.md +93 -3
  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/service_newapi.rb +1 -1
  14. data/examples/simple/call_introspect.rb +1 -0
  15. data/examples/simple/get_id.rb +2 -1
  16. data/examples/simple/properties.rb +2 -0
  17. data/examples/utils/listnames.rb +1 -0
  18. data/examples/utils/notify.rb +1 -0
  19. data/lib/dbus/api_options.rb +9 -0
  20. data/lib/dbus/auth.rb +20 -15
  21. data/lib/dbus/bus.rb +129 -74
  22. data/lib/dbus/bus_name.rb +31 -0
  23. data/lib/dbus/core_ext/class/attribute.rb +1 -1
  24. data/lib/dbus/error.rb +4 -2
  25. data/lib/dbus/introspect.rb +90 -34
  26. data/lib/dbus/logger.rb +3 -1
  27. data/lib/dbus/marshall.rb +119 -87
  28. data/lib/dbus/matchrule.rb +16 -16
  29. data/lib/dbus/message.rb +40 -27
  30. data/lib/dbus/message_queue.rb +26 -18
  31. data/lib/dbus/object.rb +401 -0
  32. data/lib/dbus/object_path.rb +28 -0
  33. data/lib/dbus/proxy_object.rb +23 -2
  34. data/lib/dbus/proxy_object_factory.rb +11 -7
  35. data/lib/dbus/proxy_object_interface.rb +26 -21
  36. data/lib/dbus/type.rb +59 -34
  37. data/lib/dbus/xml.rb +28 -17
  38. data/lib/dbus.rb +10 -8
  39. data/ruby-dbus.gemspec +8 -4
  40. data/spec/async_spec.rb +2 -0
  41. data/spec/binding_spec.rb +2 -0
  42. data/spec/bus_and_xml_backend_spec.rb +2 -0
  43. data/spec/bus_driver_spec.rb +2 -0
  44. data/spec/bus_name_spec.rb +27 -0
  45. data/spec/bus_spec.rb +2 -0
  46. data/spec/byte_array_spec.rb +2 -0
  47. data/spec/client_robustness_spec.rb +27 -0
  48. data/spec/err_msg_spec.rb +2 -0
  49. data/spec/introspect_xml_parser_spec.rb +2 -0
  50. data/spec/introspection_spec.rb +2 -0
  51. data/spec/main_loop_spec.rb +3 -1
  52. data/spec/node_spec.rb +23 -0
  53. data/spec/object_path_spec.rb +25 -0
  54. data/spec/property_spec.rb +64 -5
  55. data/spec/proxy_object_spec.rb +2 -0
  56. data/spec/server_robustness_spec.rb +2 -0
  57. data/spec/server_spec.rb +2 -0
  58. data/spec/service_newapi.rb +39 -70
  59. data/spec/session_bus_spec.rb +3 -1
  60. data/spec/session_bus_spec_manual.rb +2 -0
  61. data/spec/signal_spec.rb +5 -3
  62. data/spec/spec_helper.rb +23 -9
  63. data/spec/thread_safety_spec.rb +2 -0
  64. data/spec/tools/dbus-limited-session.conf +4 -0
  65. data/spec/type_spec.rb +2 -0
  66. data/spec/value_spec.rb +16 -1
  67. data/spec/variant_spec.rb +4 -2
  68. metadata +32 -12
  69. data/lib/dbus/export.rb +0 -131
@@ -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
  #
@@ -27,7 +29,7 @@ module DBus
27
29
  attr_accessor :path
28
30
  # The destination filter.
29
31
  attr_accessor :destination
30
- # The type type that is matched.
32
+ # @return [String] The type type that is matched.
31
33
  attr_reader :type
32
34
 
33
35
  # Create a new match rule
@@ -35,13 +37,14 @@ module DBus
35
37
  @sender = @interface = @member = @path = @destination = @type = nil
36
38
  end
37
39
 
38
- # Set the message types to filter to type _t_.
40
+ # Set the message types to filter to type _typ_.
39
41
  # Possible message types are: signal, method_call, method_return, and error.
40
- def type=(t)
41
- if !["signal", "method_call", "method_return", "error"].member?(t)
42
- raise MatchRuleException, t
42
+ def type=(typ)
43
+ if !["signal", "method_call", "method_return", "error"].member?(typ)
44
+ raise MatchRuleException, typ
43
45
  end
44
- @type = t
46
+
47
+ @type = typ
45
48
  end
46
49
 
47
50
  # Returns a match rule string version of the object. E.g.:
@@ -58,11 +61,13 @@ module DBus
58
61
  def from_s(str)
59
62
  str.split(",").each do |eq|
60
63
  next unless eq =~ /^(.*)='([^']*)'$/
64
+
61
65
  # "
62
66
  name = Regexp.last_match(1)
63
67
  val = Regexp.last_match(2)
64
68
  raise MatchRuleException, name unless FILTERS.member?(name.to_sym)
65
- method(name + "=").call(val)
69
+
70
+ method("#{name}=").call(val)
66
71
  end
67
72
  self
68
73
  end
@@ -80,18 +85,13 @@ module DBus
80
85
 
81
86
  # Determines whether a message _msg_ matches the match rule.
82
87
  def match(msg)
83
- if @type
84
- if { Message::SIGNAL => "signal", Message::METHOD_CALL => "method_call",
85
- Message::METHOD_RETURN => "method_return",
86
- Message::ERROR => "error" }[msg.message_type] != @type
87
- return false
88
- end
89
- end
88
+ return false if @type && @type != msg.message_type_s
90
89
  return false if @interface && @interface != msg.interface
91
90
  return false if @member && @member != msg.member
92
91
  return false if @path && @path != msg.path
92
+
93
93
  # FIXME: sender and destination are ignored
94
94
  true
95
95
  end
96
- end # class MatchRule
97
- end # module D-Bus
96
+ end
97
+ end
data/lib/dbus/message.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
@@ -27,7 +29,7 @@ module DBus
27
29
  # Mutex that protects updates on the serial number.
28
30
  @@serial_mutex = Mutex.new
29
31
  # Type of a message (by specification).
30
- MESSAGE_SIGNATURE = "yyyyuua(yv)".freeze
32
+ MESSAGE_SIGNATURE = "yyyyuua(yv)"
31
33
 
32
34
  # FIXME: following message type constants should be under Message::Type IMO
33
35
  # well, yeah sure
@@ -43,6 +45,9 @@ module DBus
43
45
  # Signal message type.
44
46
  SIGNAL = 4
45
47
 
48
+ # Names used by signal match rules
49
+ TYPE_NAMES = ["invalid", "method_call", "method_return", "error", "signal"].freeze
50
+
46
51
  # Message flag signyfing that no reply is expected.
47
52
  NO_REPLY_EXPECTED = 0x1
48
53
  # Message flag signifying that no automatic start is required/must be
@@ -66,11 +71,13 @@ module DBus
66
71
  attr_accessor :sender
67
72
  # The signature of the message contents.
68
73
  attr_accessor :signature
69
- # The serial number of the message this message is a reply for.
74
+ # @return [Integer] (u32)
75
+ # The serial number of the message this message is a reply for.
70
76
  attr_accessor :reply_serial
71
77
  # The protocol.
72
78
  attr_reader :protocol
73
- # The serial of the message.
79
+ # @return [Integer] (u32)
80
+ # The serial of the message.
74
81
  attr_reader :serial
75
82
  # The parameters of the message.
76
83
  attr_reader :params
@@ -105,22 +112,28 @@ module DBus
105
112
  "error_name=#{error_name}"
106
113
  end
107
114
 
108
- # Create a regular reply to a message _m_.
109
- def self.method_return(m)
110
- MethodReturnMessage.new.reply_to(m)
115
+ # @return [String] name of message type, as used in match rules:
116
+ # "method_call", "method_return", "signal", "error"
117
+ def message_type_s
118
+ TYPE_NAMES[message_type] || "unknown_type_#{message_type}"
111
119
  end
112
120
 
113
- # Create an error reply to a message _m_.
114
- def self.error(m, error_name, description = nil)
115
- ErrorMessage.new(error_name, description).reply_to(m)
121
+ # Create a regular reply to a message _msg_.
122
+ def self.method_return(msg)
123
+ MethodReturnMessage.new.reply_to(msg)
116
124
  end
117
125
 
118
- # Mark this message as a reply to a another message _m_, taking
119
- # the serial number of _m_ as reply serial and the sender of _m_ as
126
+ # Create an error reply to a message _msg_.
127
+ def self.error(msg, error_name, description = nil)
128
+ ErrorMessage.new(error_name, description).reply_to(msg)
129
+ end
130
+
131
+ # Mark this message as a reply to a another message _msg_, taking
132
+ # the serial number of _msg_ as reply serial and the sender of _msg_ as
120
133
  # destination.
121
- def reply_to(m)
122
- @reply_serial = m.serial
123
- @destination = m.sender
134
+ def reply_to(msg)
135
+ @reply_serial = msg.serial
136
+ @destination = msg.sender
124
137
  self
125
138
  end
126
139
 
@@ -223,7 +236,7 @@ module DBus
223
236
  end
224
237
  end
225
238
  pu.align(8)
226
- if @body_length > 0 && @signature
239
+ if @body_length.positive? && @signature
227
240
  @params = pu.unmarshall(@signature, @body_length)
228
241
  end
229
242
  [self, pu.idx]
@@ -231,12 +244,12 @@ module DBus
231
244
 
232
245
  # Make a new exception from ex, mark it as being caused by this message
233
246
  # @api private
234
- def annotate_exception(ex)
235
- new_ex = ex.exception("#{ex}; caused by #{self}")
236
- new_ex.set_backtrace(ex.backtrace)
237
- new_ex
247
+ def annotate_exception(exc)
248
+ new_exc = exc.exception("#{exc}; caused by #{self}")
249
+ new_exc.set_backtrace(exc.backtrace)
250
+ new_exc
238
251
  end
239
- end # class Message
252
+ end
240
253
 
241
254
  class MethodReturnMessage < Message
242
255
  def initialize
@@ -251,17 +264,17 @@ module DBus
251
264
  add_param(Type::STRING, description) unless description.nil?
252
265
  end
253
266
 
254
- def self.from_exception(ex)
255
- name = if ex.is_a? DBus::Error
256
- ex.name
267
+ def self.from_exception(exc)
268
+ name = if exc.is_a? DBus::Error
269
+ exc.name
257
270
  else
258
271
  "org.freedesktop.DBus.Error.Failed"
259
- # ex.class.to_s # RuntimeError is not a valid name, has no dot
272
+ # exc.class.to_s # RuntimeError is not a valid name, has no dot
260
273
  end
261
- description = ex.message
274
+ description = exc.message
262
275
  msg = new(name, description)
263
- msg.add_param(DBus.type("as"), ex.backtrace)
276
+ msg.add_param(DBus.type("as"), exc.backtrace)
264
277
  msg
265
278
  end
266
279
  end
267
- end # module DBus
280
+ 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
@@ -11,6 +13,7 @@ require "fcntl"
11
13
  require "socket"
12
14
 
13
15
  module DBus
16
+ # Encapsulates a socket so that we can {#push} and {#pop} {Message}s.
14
17
  class MessageQueue
15
18
  # The socket that is used to connect with the bus.
16
19
  attr_reader :socket
@@ -22,14 +25,16 @@ module DBus
22
25
  connect
23
26
  end
24
27
 
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)
28
+ # @param blocking [Boolean]
29
+ # true: wait to return a {Message};
30
+ # false: may return `nil`
31
+ # @return [Message,nil] one message or nil if unavailable
32
+ # @raise EOFError
33
+ # @todo failure modes
34
+ def pop(blocking: true)
30
35
  buffer_from_socket_nonblock
31
36
  message = message_from_buffer_nonblock
32
- unless non_block
37
+ if blocking
33
38
  # we can block
34
39
  while message.nil?
35
40
  r, _d, _d = IO.select([@socket])
@@ -53,7 +58,7 @@ module DBus
53
58
  def connect
54
59
  addresses = @address.split ";"
55
60
  # connect to first one that succeeds
56
- worked = addresses.find do |a|
61
+ addresses.find do |a|
57
62
  transport, keyvaluestring = a.split ":"
58
63
  kv_list = keyvaluestring.split ","
59
64
  kv_hash = {}
@@ -73,29 +78,29 @@ module DBus
73
78
  # ignore, report?
74
79
  end
75
80
  end
76
- worked
77
81
  # returns the address that worked or nil.
78
82
  # how to report failure?
79
83
  end
80
84
 
81
85
  # Connect to a bus over tcp and initialize the connection.
82
86
  def connect_to_tcp(params)
83
- # check if the path is sufficient
84
- if params.key?("host") && params.key?("port")
87
+ host = params["host"]
88
+ port = params["port"]
89
+ if host && port
85
90
  begin
86
91
  # initialize the tcp socket
87
- @socket = TCPSocket.new(params["host"], params["port"].to_i)
92
+ @socket = TCPSocket.new(host, port.to_i)
88
93
  @socket.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
89
94
  init_connection
90
95
  @is_tcp = true
91
96
  rescue Exception => e
92
97
  puts "Oops:", e
93
- puts "Error: Could not establish connection to: #{@path}, will now exit."
98
+ puts "Error: Could not establish connection to: #{host}:#{port}, will now exit."
94
99
  exit(1) # a little harsh
95
100
  end
96
101
  else
97
102
  # Danger, Will Robinson: the specified "path" is not usable
98
- puts "Error: supplied path: #{@path}, unusable! sorry."
103
+ puts "Error: supplied params: #{@params}, unusable! sorry."
99
104
  end
100
105
  end
101
106
 
@@ -124,22 +129,23 @@ module DBus
124
129
 
125
130
  # Initialize the connection to the bus.
126
131
  def init_connection
127
- @client = Client.new(@socket)
128
- @client.authenticate
132
+ client = Client.new(@socket)
133
+ client.authenticate
129
134
  end
130
135
 
131
136
  public # FIXME: fix Main loop instead
132
137
 
133
138
  # Get and remove one message from the buffer.
134
- # Return the message or nil.
139
+ # @return [Message,nil] the message or nil if unavailable
135
140
  def message_from_buffer_nonblock
136
141
  return nil if @buffer.empty?
142
+
137
143
  ret = nil
138
144
  begin
139
145
  ret, size = Message.new.unmarshall_buffer(@buffer)
140
146
  @buffer.slice!(0, size)
141
147
  rescue IncompleteBufferException
142
- # fall through, let ret be null
148
+ # fall through, let ret remain nil
143
149
  end
144
150
  ret
145
151
  end
@@ -149,7 +155,8 @@ module DBus
149
155
 
150
156
  # Fill (append) the buffer from data that might be available on the
151
157
  # socket.
152
- # EOFError may be raised
158
+ # @return [void]
159
+ # @raise EOFError
153
160
  def buffer_from_socket_nonblock
154
161
  @buffer += @socket.read_nonblock(MSG_BUF_SIZE)
155
162
  rescue EOFError
@@ -159,6 +166,7 @@ module DBus
159
166
  rescue Exception => e
160
167
  puts "Oops:", e
161
168
  raise if @is_tcp # why?
169
+
162
170
  puts "WARNING: read_nonblock failed, falling back to .recv"
163
171
  @buffer += @socket.recv(MSG_BUF_SIZE)
164
172
  end