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
data/lib/dbus/matchrule.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
|
#
|
@@ -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
|
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=(
|
41
|
-
if !["signal", "method_call", "method_return", "error"].member?(
|
42
|
-
raise MatchRuleException,
|
42
|
+
def type=(typ)
|
43
|
+
if !["signal", "method_call", "method_return", "error"].member?(typ)
|
44
|
+
raise MatchRuleException, typ
|
43
45
|
end
|
44
|
-
|
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
|
-
|
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
|
97
|
-
end
|
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)"
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
109
|
-
|
110
|
-
|
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
|
114
|
-
def self.
|
115
|
-
|
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
|
-
#
|
119
|
-
|
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(
|
122
|
-
@reply_serial =
|
123
|
-
@destination =
|
134
|
+
def reply_to(msg)
|
135
|
+
@reply_serial = msg.serial
|
136
|
+
@destination = msg.sender
|
124
137
|
self
|
125
138
|
end
|
126
139
|
|
@@ -159,7 +172,7 @@ module DBus
|
|
159
172
|
@body_length = params.packet.bytesize
|
160
173
|
|
161
174
|
marshaller = PacketMarshaller.new
|
162
|
-
marshaller.append(Type::BYTE, HOST_END)
|
175
|
+
marshaller.append(Type::BYTE, HOST_END.ord)
|
163
176
|
marshaller.append(Type::BYTE, @message_type)
|
164
177
|
marshaller.append(Type::BYTE, @flags)
|
165
178
|
marshaller.append(Type::BYTE, @protocol)
|
@@ -191,13 +204,7 @@ module DBus
|
|
191
204
|
# the detected message (self) and
|
192
205
|
# the index pointer of the buffer where the message data ended.
|
193
206
|
def unmarshall_buffer(buf)
|
194
|
-
|
195
|
-
endianness = if buf[0] == "l"
|
196
|
-
LIL_END
|
197
|
-
else
|
198
|
-
BIG_END
|
199
|
-
end
|
200
|
-
pu = PacketUnmarshaller.new(buf, endianness)
|
207
|
+
pu = PacketUnmarshaller.new(buf, RawMessage.endianness(buf[0]))
|
201
208
|
mdata = pu.unmarshall(MESSAGE_SIGNATURE)
|
202
209
|
_, @message_type, @flags, @protocol, @body_length, @serial,
|
203
210
|
headers = mdata
|
@@ -222,21 +229,21 @@ module DBus
|
|
222
229
|
@signature = struct[1]
|
223
230
|
end
|
224
231
|
end
|
225
|
-
pu.
|
226
|
-
if @body_length
|
232
|
+
pu.align_body
|
233
|
+
if @body_length.positive? && @signature
|
227
234
|
@params = pu.unmarshall(@signature, @body_length)
|
228
235
|
end
|
229
|
-
[self, pu.
|
236
|
+
[self, pu.consumed_size]
|
230
237
|
end
|
231
238
|
|
232
239
|
# Make a new exception from ex, mark it as being caused by this message
|
233
240
|
# @api private
|
234
|
-
def annotate_exception(
|
235
|
-
|
236
|
-
|
237
|
-
|
241
|
+
def annotate_exception(exc)
|
242
|
+
new_exc = exc.exception("#{exc}; caused by #{self}")
|
243
|
+
new_exc.set_backtrace(exc.backtrace)
|
244
|
+
new_exc
|
238
245
|
end
|
239
|
-
end
|
246
|
+
end
|
240
247
|
|
241
248
|
class MethodReturnMessage < Message
|
242
249
|
def initialize
|
@@ -251,17 +258,17 @@ module DBus
|
|
251
258
|
add_param(Type::STRING, description) unless description.nil?
|
252
259
|
end
|
253
260
|
|
254
|
-
def self.from_exception(
|
255
|
-
name = if
|
256
|
-
|
261
|
+
def self.from_exception(exc)
|
262
|
+
name = if exc.is_a? DBus::Error
|
263
|
+
exc.name
|
257
264
|
else
|
258
265
|
"org.freedesktop.DBus.Error.Failed"
|
259
|
-
#
|
266
|
+
# exc.class.to_s # RuntimeError is not a valid name, has no dot
|
260
267
|
end
|
261
|
-
description =
|
268
|
+
description = exc.message
|
262
269
|
msg = new(name, description)
|
263
|
-
msg.add_param(DBus.type("as"),
|
270
|
+
msg.add_param(DBus.type("as"), exc.backtrace)
|
264
271
|
msg
|
265
272
|
end
|
266
273
|
end
|
267
|
-
end
|
274
|
+
end
|
data/lib/dbus/message_queue.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
|
@@ -23,14 +25,16 @@ module DBus
|
|
23
25
|
connect
|
24
26
|
end
|
25
27
|
|
26
|
-
# @param
|
28
|
+
# @param blocking [Boolean]
|
29
|
+
# true: wait to return a {Message};
|
30
|
+
# false: may return `nil`
|
27
31
|
# @return [Message,nil] one message or nil if unavailable
|
28
32
|
# @raise EOFError
|
29
33
|
# @todo failure modes
|
30
|
-
def pop(
|
34
|
+
def pop(blocking: true)
|
31
35
|
buffer_from_socket_nonblock
|
32
36
|
message = message_from_buffer_nonblock
|
33
|
-
|
37
|
+
if blocking
|
34
38
|
# we can block
|
35
39
|
while message.nil?
|
36
40
|
r, _d, _d = IO.select([@socket])
|
@@ -54,7 +58,7 @@ module DBus
|
|
54
58
|
def connect
|
55
59
|
addresses = @address.split ";"
|
56
60
|
# connect to first one that succeeds
|
57
|
-
|
61
|
+
addresses.find do |a|
|
58
62
|
transport, keyvaluestring = a.split ":"
|
59
63
|
kv_list = keyvaluestring.split ","
|
60
64
|
kv_hash = {}
|
@@ -74,29 +78,29 @@ module DBus
|
|
74
78
|
# ignore, report?
|
75
79
|
end
|
76
80
|
end
|
77
|
-
worked
|
78
81
|
# returns the address that worked or nil.
|
79
82
|
# how to report failure?
|
80
83
|
end
|
81
84
|
|
82
85
|
# Connect to a bus over tcp and initialize the connection.
|
83
86
|
def connect_to_tcp(params)
|
84
|
-
|
85
|
-
|
87
|
+
host = params["host"]
|
88
|
+
port = params["port"]
|
89
|
+
if host && port
|
86
90
|
begin
|
87
91
|
# initialize the tcp socket
|
88
|
-
@socket = TCPSocket.new(
|
92
|
+
@socket = TCPSocket.new(host, port.to_i)
|
89
93
|
@socket.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
90
94
|
init_connection
|
91
95
|
@is_tcp = true
|
92
96
|
rescue Exception => e
|
93
97
|
puts "Oops:", e
|
94
|
-
puts "Error: Could not establish connection to: #{
|
98
|
+
puts "Error: Could not establish connection to: #{host}:#{port}, will now exit."
|
95
99
|
exit(1) # a little harsh
|
96
100
|
end
|
97
101
|
else
|
98
102
|
# Danger, Will Robinson: the specified "path" is not usable
|
99
|
-
puts "Error: supplied
|
103
|
+
puts "Error: supplied params: #{@params}, unusable! sorry."
|
100
104
|
end
|
101
105
|
end
|
102
106
|
|
@@ -135,6 +139,7 @@ module DBus
|
|
135
139
|
# @return [Message,nil] the message or nil if unavailable
|
136
140
|
def message_from_buffer_nonblock
|
137
141
|
return nil if @buffer.empty?
|
142
|
+
|
138
143
|
ret = nil
|
139
144
|
begin
|
140
145
|
ret, size = Message.new.unmarshall_buffer(@buffer)
|
@@ -161,6 +166,7 @@ module DBus
|
|
161
166
|
rescue Exception => e
|
162
167
|
puts "Oops:", e
|
163
168
|
raise if @is_tcp # why?
|
169
|
+
|
164
170
|
puts "WARNING: read_nonblock failed, falling back to .recv"
|
165
171
|
@buffer += @socket.recv(MSG_BUF_SIZE)
|
166
172
|
end
|