ruby-dbus 0.15.0 → 0.18.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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