ruby-dbus 0.16.0 → 0.18.1
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.
- 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/api_options.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) 2016 Martin Vidner
|
3
5
|
#
|
@@ -9,6 +11,13 @@
|
|
9
11
|
module DBus
|
10
12
|
class ApiOptions
|
11
13
|
# https://github.com/mvidner/ruby-dbus/issues/30
|
14
|
+
# @return [Boolean]
|
15
|
+
# - true: a proxy (client-side) method will return an array
|
16
|
+
# even for the most common case where the method is declared
|
17
|
+
# to have only one 'out parameter'
|
18
|
+
# - false: a proxy (client-side) method will return
|
19
|
+
# - one value for the only 'out parameter'
|
20
|
+
# - an array with more 'out parameters'
|
12
21
|
attr_accessor :proxy_method_returns_array
|
13
22
|
|
14
23
|
A0 = ApiOptions.new
|
data/lib/dbus/auth.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
|
#
|
@@ -73,7 +75,7 @@ module DBus
|
|
73
75
|
path = File.join(ENV["HOME"], ".dbus-keyrings", context)
|
74
76
|
DBus.logger.debug "path: #{path.inspect}"
|
75
77
|
File.foreach(path) do |line|
|
76
|
-
if line.
|
78
|
+
if line.start_with?(id)
|
77
79
|
# Right line of file, read cookie
|
78
80
|
cookie = line.split(" ")[2].chomp
|
79
81
|
DBus.logger.debug "cookie: #{cookie.inspect}"
|
@@ -87,27 +89,28 @@ module DBus
|
|
87
89
|
return response
|
88
90
|
end
|
89
91
|
end
|
92
|
+
return if @retries <= 0
|
93
|
+
|
90
94
|
# a little rescue magic
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
data(hexdata)
|
97
|
-
end
|
95
|
+
puts "ERROR: Could not auth, will now exit."
|
96
|
+
puts "ERROR: Unable to locate cookie, retry in 1 second."
|
97
|
+
@retries -= 1
|
98
|
+
sleep 1
|
99
|
+
data(hexdata)
|
98
100
|
end
|
99
101
|
|
100
102
|
# encode plain to hex
|
101
103
|
def hex_encode(plain)
|
102
104
|
return nil if plain.nil?
|
103
|
-
|
105
|
+
|
106
|
+
plain.to_s.unpack1("H*")
|
104
107
|
end
|
105
108
|
|
106
109
|
# decode hex to plain
|
107
110
|
def hex_decode(encoded)
|
108
111
|
encoded.scan(/[[:xdigit:]]{2}/).map { |h| h.hex.chr }.join
|
109
112
|
end
|
110
|
-
end
|
113
|
+
end
|
111
114
|
|
112
115
|
# Note: this following stuff is tested with External authenticator only!
|
113
116
|
|
@@ -148,12 +151,13 @@ module DBus
|
|
148
151
|
# server.
|
149
152
|
def send(meth, *args)
|
150
153
|
o = ([meth] + args).join(" ")
|
151
|
-
@socket.write(o
|
154
|
+
@socket.write("#{o}\r\n")
|
152
155
|
end
|
153
156
|
|
154
157
|
# Try authentication using the next authenticator.
|
155
158
|
def next_authenticator
|
156
159
|
raise AuthenticationFailed if @auth_list.empty?
|
160
|
+
|
157
161
|
@authenticator = @auth_list.shift.new
|
158
162
|
auth_msg = ["AUTH", @authenticator.name, @authenticator.authenticate]
|
159
163
|
DBus.logger.debug "auth_msg: #{auth_msg.inspect}"
|
@@ -169,9 +173,10 @@ module DBus
|
|
169
173
|
data = ""
|
170
174
|
crlf = "\r\n"
|
171
175
|
left = 1024 # 1024 byte, no idea if it's ever getting bigger
|
172
|
-
while left
|
176
|
+
while left.positive?
|
173
177
|
buf = @socket.read(left > 1 ? 1 : left)
|
174
178
|
break if buf.nil?
|
179
|
+
|
175
180
|
left -= buf.bytesize
|
176
181
|
data += buf
|
177
182
|
break if data.include? crlf # crlf means line finished, the TCP socket keeps on listening, so we break
|
@@ -262,6 +267,6 @@ module DBus
|
|
262
267
|
end
|
263
268
|
end
|
264
269
|
true
|
265
|
-
end
|
266
|
-
end
|
267
|
-
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
data/lib/dbus/bus.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
|
@@ -9,7 +11,6 @@
|
|
9
11
|
# See the file "COPYING" for the exact licensing terms.
|
10
12
|
|
11
13
|
require "socket"
|
12
|
-
require "thread"
|
13
14
|
require "singleton"
|
14
15
|
|
15
16
|
# = D-Bus main module
|
@@ -17,7 +18,7 @@ require "singleton"
|
|
17
18
|
# Module containing all the D-Bus modules and classes.
|
18
19
|
module DBus
|
19
20
|
# This represents a remote service. It should not be instantiated directly
|
20
|
-
# Use {
|
21
|
+
# Use {Connection#service}
|
21
22
|
class Service
|
22
23
|
# The service name.
|
23
24
|
attr_reader :name
|
@@ -48,6 +49,7 @@ module DBus
|
|
48
49
|
end
|
49
50
|
|
50
51
|
# Retrieves an object at the given _path_.
|
52
|
+
# @param path [ObjectPath]
|
51
53
|
# @return [ProxyObject]
|
52
54
|
def [](path)
|
53
55
|
object(path, api: ApiOptions::A1)
|
@@ -55,9 +57,11 @@ module DBus
|
|
55
57
|
|
56
58
|
# Retrieves an object at the given _path_
|
57
59
|
# whose methods always return an array.
|
60
|
+
# @param path [ObjectPath]
|
61
|
+
# @param api [ApiOptions]
|
58
62
|
# @return [ProxyObject]
|
59
63
|
def object(path, api: ApiOptions::A0)
|
60
|
-
node = get_node(path,
|
64
|
+
node = get_node(path, create: true)
|
61
65
|
if node.object.nil? || node.object.api != api
|
62
66
|
node.object = ProxyObject.new(
|
63
67
|
@bus, @name, path,
|
@@ -67,35 +71,43 @@ module DBus
|
|
67
71
|
node.object
|
68
72
|
end
|
69
73
|
|
70
|
-
# Export an object
|
74
|
+
# Export an object
|
75
|
+
# @param obj [DBus::Object]
|
71
76
|
def export(obj)
|
72
77
|
obj.service = self
|
73
|
-
get_node(obj.path, true).object = obj
|
78
|
+
get_node(obj.path, create: true).object = obj
|
74
79
|
end
|
75
80
|
|
76
81
|
# Undo exporting an object _obj_.
|
77
82
|
# Raises ArgumentError if it is not a DBus::Object.
|
78
83
|
# Returns the object, or false if _obj_ was not exported.
|
84
|
+
# @param obj [DBus::Object]
|
79
85
|
def unexport(obj)
|
80
86
|
raise ArgumentError, "DBus::Service#unexport() expects a DBus::Object argument" unless obj.is_a?(DBus::Object)
|
81
87
|
return false unless obj.path
|
88
|
+
|
82
89
|
last_path_separator_idx = obj.path.rindex("/")
|
83
90
|
parent_path = obj.path[1..last_path_separator_idx - 1]
|
84
91
|
node_name = obj.path[last_path_separator_idx + 1..-1]
|
85
92
|
|
86
|
-
parent_node = get_node(parent_path, false)
|
93
|
+
parent_node = get_node(parent_path, create: false)
|
87
94
|
return false unless parent_node
|
95
|
+
|
88
96
|
obj.service = nil
|
89
97
|
parent_node.delete(node_name).object
|
90
98
|
end
|
91
99
|
|
92
|
-
# Get the object node corresponding to the given
|
93
|
-
#
|
94
|
-
|
100
|
+
# Get the object node corresponding to the given *path*.
|
101
|
+
# @param path [ObjectPath]
|
102
|
+
# @param create [Boolean] if true, the the {Node}s in the path are created
|
103
|
+
# if they do not already exist.
|
104
|
+
# @return [Node,nil]
|
105
|
+
def get_node(path, create: false)
|
95
106
|
n = @root
|
96
107
|
path.sub(%r{^/}, "").split("/").each do |elem|
|
97
108
|
if !(n[elem])
|
98
109
|
return nil if !create
|
110
|
+
|
99
111
|
n[elem] = Node.new(elem)
|
100
112
|
end
|
101
113
|
n = n[elem]
|
@@ -120,13 +132,14 @@ module DBus
|
|
120
132
|
subnodes.each do |nodename|
|
121
133
|
subnode = node[nodename] = Node.new(nodename)
|
122
134
|
subpath = if path == "/"
|
123
|
-
"
|
135
|
+
"/#{nodename}"
|
124
136
|
else
|
125
|
-
path
|
137
|
+
"#{path}/#{nodename}"
|
126
138
|
end
|
127
139
|
rec_introspect(subnode, subpath)
|
128
140
|
end
|
129
141
|
return if intfs.empty?
|
142
|
+
|
130
143
|
node.object = ProxyObjectFactory.new(xml, @bus, @name, path).build
|
131
144
|
end
|
132
145
|
end
|
@@ -135,34 +148,34 @@ module DBus
|
|
135
148
|
#
|
136
149
|
# Class representing a node on an object path.
|
137
150
|
class Node < Hash
|
138
|
-
#
|
151
|
+
# @return [DBus::Object,DBus::ProxyObject,nil]
|
152
|
+
# The D-Bus object contained by the node.
|
139
153
|
attr_accessor :object
|
154
|
+
|
140
155
|
# The name of the node.
|
156
|
+
# @return [String] the last component of its object path, or "/"
|
141
157
|
attr_reader :name
|
142
158
|
|
143
159
|
# Create a new node with a given _name_.
|
144
160
|
def initialize(name)
|
161
|
+
super()
|
145
162
|
@name = name
|
146
163
|
@object = nil
|
147
164
|
end
|
148
165
|
|
149
166
|
# Return an XML string representation of the node.
|
150
167
|
# It is shallow, not recursing into subnodes
|
151
|
-
|
168
|
+
# @param node_opath [String]
|
169
|
+
def to_xml(node_opath)
|
152
170
|
xml = '<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
|
153
171
|
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
154
|
-
<node>
|
155
172
|
'
|
156
|
-
|
157
|
-
|
173
|
+
xml += "<node name=\"#{node_opath}\">\n"
|
174
|
+
each_key do |k|
|
175
|
+
xml += " <node name=\"#{k}\" />\n"
|
158
176
|
end
|
159
|
-
|
160
|
-
|
161
|
-
xml += %(<interface name="#{v.name}">\n)
|
162
|
-
v.methods.each_value { |m| xml += m.to_xml }
|
163
|
-
v.signals.each_value { |m| xml += m.to_xml }
|
164
|
-
xml += "</interface>\n"
|
165
|
-
end
|
177
|
+
@object&.intfs&.each_value do |v|
|
178
|
+
xml += v.to_xml
|
166
179
|
end
|
167
180
|
xml += "</node>"
|
168
181
|
xml
|
@@ -180,9 +193,12 @@ module DBus
|
|
180
193
|
if !@object.nil?
|
181
194
|
s += format("%x ", @object.object_id)
|
182
195
|
end
|
183
|
-
|
196
|
+
contents_sub_inspect = keys
|
197
|
+
.map { |k| "#{k} => #{self[k].sub_inspect}" }
|
198
|
+
.join(",")
|
199
|
+
"#{s}{#{contents_sub_inspect}}"
|
184
200
|
end
|
185
|
-
end
|
201
|
+
end
|
186
202
|
|
187
203
|
# FIXME: rename Connection to Bus?
|
188
204
|
|
@@ -205,7 +221,15 @@ module DBus
|
|
205
221
|
def initialize(path)
|
206
222
|
@message_queue = MessageQueue.new(path)
|
207
223
|
@unique_name = nil
|
224
|
+
|
225
|
+
# @return [Hash{Integer => Proc}]
|
226
|
+
# key: message serial
|
227
|
+
# value: block to be run when the reply to that message is received
|
208
228
|
@method_call_replies = {}
|
229
|
+
|
230
|
+
# @return [Hash{Integer => Message}]
|
231
|
+
# for debugging only: messages for which a reply was not received yet;
|
232
|
+
# key == value.serial
|
209
233
|
@method_call_msgs = {}
|
210
234
|
@signal_matchrules = {}
|
211
235
|
@proxy = nil
|
@@ -216,7 +240,7 @@ module DBus
|
|
216
240
|
# but do not block on the queue.
|
217
241
|
# Called by a main loop when something is available in the queue
|
218
242
|
def dispatch_message_queue
|
219
|
-
while (msg = @message_queue.pop(:
|
243
|
+
while (msg = @message_queue.pop(blocking: false)) # FIXME: EOFError
|
220
244
|
process(msg)
|
221
245
|
end
|
222
246
|
end
|
@@ -323,7 +347,7 @@ module DBus
|
|
323
347
|
</signal>
|
324
348
|
</interface>
|
325
349
|
</node>
|
326
|
-
'
|
350
|
+
'
|
327
351
|
# This apostroph is for syntax highlighting editors confused by above xml: "
|
328
352
|
|
329
353
|
# @api private
|
@@ -338,6 +362,7 @@ module DBus
|
|
338
362
|
if reply_handler.nil?
|
339
363
|
send_sync(message) do |rmsg|
|
340
364
|
raise rmsg if rmsg.is_a?(Error)
|
365
|
+
|
341
366
|
ret = rmsg.params
|
342
367
|
end
|
343
368
|
else
|
@@ -442,44 +467,52 @@ module DBus
|
|
442
467
|
end
|
443
468
|
|
444
469
|
# @api private
|
445
|
-
# Send a message
|
470
|
+
# Send a message _msg_ on to the bus. This is done synchronously, thus
|
446
471
|
# the call will block until a reply message arrives.
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
472
|
+
# @param msg [Message]
|
473
|
+
# @param retc [Proc] the reply handler
|
474
|
+
# @yieldparam rmsg [MethodReturnMessage] the reply
|
475
|
+
# @yieldreturn [Array<Object>] the reply (out) parameters
|
476
|
+
def send_sync(msg, &retc) # :yields: reply/return message
|
477
|
+
return if msg.nil? # check if somethings wrong
|
478
|
+
|
479
|
+
@message_queue.push(msg)
|
480
|
+
@method_call_msgs[msg.serial] = msg
|
481
|
+
@method_call_replies[msg.serial] = retc
|
452
482
|
|
453
483
|
retm = wait_for_message
|
454
484
|
return if retm.nil? # check if somethings wrong
|
455
485
|
|
456
486
|
process(retm)
|
457
|
-
while @method_call_replies.key?
|
487
|
+
while @method_call_replies.key? msg.serial
|
458
488
|
retm = wait_for_message
|
459
489
|
process(retm)
|
460
490
|
end
|
461
491
|
rescue EOFError
|
462
|
-
new_err = DBus::Error.new("Connection dropped after we sent #{
|
492
|
+
new_err = DBus::Error.new("Connection dropped after we sent #{msg.inspect}")
|
463
493
|
raise new_err
|
464
494
|
end
|
465
495
|
|
466
496
|
# @api private
|
467
497
|
# Specify a code block that has to be executed when a reply for
|
468
|
-
# message
|
469
|
-
|
498
|
+
# message _msg_ is received.
|
499
|
+
# @param msg [Message]
|
500
|
+
def on_return(msg, &retc)
|
470
501
|
# Have a better exception here
|
471
|
-
if
|
502
|
+
if msg.message_type != Message::METHOD_CALL
|
472
503
|
raise "on_return should only get method_calls"
|
473
504
|
end
|
474
|
-
|
475
|
-
@
|
505
|
+
|
506
|
+
@method_call_msgs[msg.serial] = msg
|
507
|
+
@method_call_replies[msg.serial] = retc
|
476
508
|
end
|
477
509
|
|
478
510
|
# Asks bus to send us messages matching mr, and execute slot when
|
479
511
|
# received
|
480
|
-
|
512
|
+
# @param match_rule [MatchRule,#to_s]
|
513
|
+
def add_match(match_rule, &slot)
|
481
514
|
# check this is a signal.
|
482
|
-
mrs =
|
515
|
+
mrs = match_rule.to_s
|
483
516
|
DBus.logger.debug "#{@signal_matchrules.size} rules, adding #{mrs.inspect}"
|
484
517
|
# don't ask for the same match if we override it
|
485
518
|
unless @signal_matchrules.key?(mrs)
|
@@ -489,69 +522,77 @@ module DBus
|
|
489
522
|
@signal_matchrules[mrs] = slot
|
490
523
|
end
|
491
524
|
|
492
|
-
|
493
|
-
|
525
|
+
# @param match_rule [MatchRule,#to_s]
|
526
|
+
def remove_match(match_rule)
|
527
|
+
mrs = match_rule.to_s
|
494
528
|
rule_existed = @signal_matchrules.delete(mrs).nil?
|
495
529
|
# don't remove nonexisting matches.
|
496
530
|
return if rule_existed
|
531
|
+
|
497
532
|
# FIXME: if we do try, the Error.MatchRuleNotFound is *not* raised
|
498
533
|
# and instead is reported as "no return code for nil"
|
499
534
|
proxy.RemoveMatch(mrs)
|
500
535
|
end
|
501
536
|
|
502
537
|
# @api private
|
503
|
-
# Process a message
|
504
|
-
|
505
|
-
|
506
|
-
|
538
|
+
# Process a message _msg_ based on its type.
|
539
|
+
# @param msg [Message]
|
540
|
+
def process(msg)
|
541
|
+
return if msg.nil? # check if somethings wrong
|
542
|
+
|
543
|
+
case msg.message_type
|
507
544
|
when Message::ERROR, Message::METHOD_RETURN
|
508
|
-
raise InvalidPacketException if
|
509
|
-
|
545
|
+
raise InvalidPacketException if msg.reply_serial.nil?
|
546
|
+
|
547
|
+
mcs = @method_call_replies[msg.reply_serial]
|
510
548
|
if !mcs
|
511
|
-
DBus.logger.debug "no return code for mcs: #{mcs.inspect}
|
549
|
+
DBus.logger.debug "no return code for mcs: #{mcs.inspect} msg: #{msg.inspect}"
|
512
550
|
else
|
513
|
-
if
|
514
|
-
mcs.call(Error.new(
|
551
|
+
if msg.message_type == Message::ERROR
|
552
|
+
mcs.call(Error.new(msg))
|
515
553
|
else
|
516
|
-
mcs.call(
|
554
|
+
mcs.call(msg)
|
517
555
|
end
|
518
|
-
@method_call_replies.delete(
|
519
|
-
@method_call_msgs.delete(
|
556
|
+
@method_call_replies.delete(msg.reply_serial)
|
557
|
+
@method_call_msgs.delete(msg.reply_serial)
|
520
558
|
end
|
521
559
|
when DBus::Message::METHOD_CALL
|
522
|
-
if
|
560
|
+
if msg.path == "/org/freedesktop/DBus"
|
523
561
|
DBus.logger.debug "Got method call on /org/freedesktop/DBus"
|
524
562
|
end
|
525
|
-
node = @service.get_node(
|
563
|
+
node = @service.get_node(msg.path, create: false)
|
526
564
|
if !node
|
527
|
-
reply = Message.error(
|
528
|
-
"Object #{
|
565
|
+
reply = Message.error(msg, "org.freedesktop.DBus.Error.UnknownObject",
|
566
|
+
"Object #{msg.path} doesn't exist")
|
529
567
|
@message_queue.push(reply)
|
530
568
|
# handle introspectable as an exception:
|
531
|
-
elsif
|
532
|
-
|
533
|
-
reply = Message.new(Message::METHOD_RETURN).reply_to(
|
569
|
+
elsif msg.interface == "org.freedesktop.DBus.Introspectable" &&
|
570
|
+
msg.member == "Introspect"
|
571
|
+
reply = Message.new(Message::METHOD_RETURN).reply_to(msg)
|
534
572
|
reply.sender = @unique_name
|
535
|
-
|
573
|
+
xml = node.to_xml(msg.path)
|
574
|
+
reply.add_param(Type::STRING, xml)
|
536
575
|
@message_queue.push(reply)
|
537
576
|
else
|
538
577
|
obj = node.object
|
539
578
|
return if obj.nil? # FIXME, pushes no reply
|
540
|
-
|
579
|
+
|
580
|
+
obj&.dispatch(msg)
|
541
581
|
end
|
542
582
|
when DBus::Message::SIGNAL
|
543
583
|
# the signal can match multiple different rules
|
544
584
|
# clone to allow new signale handlers to be registered
|
545
585
|
@signal_matchrules.dup.each do |mrs, slot|
|
546
|
-
if DBus::MatchRule.new.from_s(mrs).match(
|
547
|
-
slot.call(
|
586
|
+
if DBus::MatchRule.new.from_s(mrs).match(msg)
|
587
|
+
slot.call(msg)
|
548
588
|
end
|
549
589
|
end
|
550
590
|
else
|
551
|
-
|
591
|
+
# spec(Message Format): Unknown types must be ignored.
|
592
|
+
DBus.logger.debug "Unknown message type: #{msg.message_type}"
|
552
593
|
end
|
553
|
-
rescue Exception =>
|
554
|
-
raise
|
594
|
+
rescue Exception => e
|
595
|
+
raise msg.annotate_exception(e)
|
555
596
|
end
|
556
597
|
|
557
598
|
# Retrieves the Service with the given _name_.
|
@@ -566,6 +607,11 @@ module DBus
|
|
566
607
|
# @api private
|
567
608
|
# Emit a signal event for the given _service_, object _obj_, interface
|
568
609
|
# _intf_ and signal _sig_ with arguments _args_.
|
610
|
+
# @param service [Service]
|
611
|
+
# @param obj [DBus::Object]
|
612
|
+
# @param intf [Interface]
|
613
|
+
# @param sig [Signal]
|
614
|
+
# @param args arguments for the signal
|
569
615
|
def emit(service, obj, intf, sig, *args)
|
570
616
|
m = Message.new(DBus::Message::SIGNAL)
|
571
617
|
m.path = obj.path
|
@@ -596,7 +642,7 @@ module DBus
|
|
596
642
|
end
|
597
643
|
@service = Service.new(@unique_name, self)
|
598
644
|
end
|
599
|
-
end
|
645
|
+
end
|
600
646
|
|
601
647
|
# = D-Bus session bus class
|
602
648
|
#
|
@@ -622,6 +668,7 @@ module DBus
|
|
622
668
|
# traditional dbus uses /var/lib/dbus/machine-id
|
623
669
|
machine_id_path = Dir["{/etc,/var/lib/dbus,/var/db/dbus}/machine-id"].first
|
624
670
|
return nil unless machine_id_path
|
671
|
+
|
625
672
|
machine_id = File.read(machine_id_path).chomp
|
626
673
|
|
627
674
|
display = ENV["DISPLAY"][/:(\d+)\.?/, 1]
|
@@ -653,7 +700,7 @@ module DBus
|
|
653
700
|
class ASystemBus < Connection
|
654
701
|
# Get the default system bus.
|
655
702
|
def initialize
|
656
|
-
super(
|
703
|
+
super(SYSTEM_BUS_ADDRESS)
|
657
704
|
send_hello
|
658
705
|
end
|
659
706
|
end
|
@@ -668,7 +715,7 @@ module DBus
|
|
668
715
|
# (for Unix-socket) unix:path=/tmp/my_funky_bus_socket
|
669
716
|
#
|
670
717
|
# you'll need to take care about authentification then, more info here:
|
671
|
-
#
|
718
|
+
# https://gitlab.com/pangdudu/ruby-dbus/-/blob/master/README.rdoc
|
672
719
|
class RemoteBus < Connection
|
673
720
|
# Get the remote bus.
|
674
721
|
def initialize(socket_name)
|
@@ -728,6 +775,7 @@ module DBus
|
|
728
775
|
while !@quitting && !@buses.empty?
|
729
776
|
ready = IO.select(@buses.keys, [], [], 5) # timeout 5 seconds
|
730
777
|
next unless ready # timeout exceeds so continue unless quitting
|
778
|
+
|
731
779
|
ready.first.each do |socket|
|
732
780
|
b = @buses[socket]
|
733
781
|
begin
|
@@ -742,5 +790,5 @@ module DBus
|
|
742
790
|
end
|
743
791
|
end
|
744
792
|
end
|
745
|
-
end
|
746
|
-
end
|
793
|
+
end
|
794
|
+
end
|
data/lib/dbus/bus_name.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) 2019 Martin Vidner
|
3
5
|
#
|
@@ -7,21 +9,23 @@
|
|
7
9
|
# See the file "COPYING" for the exact licensing terms.
|
8
10
|
|
9
11
|
module DBus
|
10
|
-
#
|
12
|
+
# D-Bus: a name for a connection, like ":1.3" or "org.example.ManagerManager".
|
13
|
+
# Implemented as a {::String} that validates at initialization time.
|
11
14
|
# @see https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names-bus
|
12
15
|
class BusName < String
|
13
16
|
# @raise Error if not a valid bus name
|
14
|
-
def initialize(
|
15
|
-
unless self.class.valid?(
|
16
|
-
raise DBus::Error, "Invalid bus name #{
|
17
|
+
def initialize(name)
|
18
|
+
unless self.class.valid?(name)
|
19
|
+
raise DBus::Error, "Invalid bus name #{name.inspect}"
|
17
20
|
end
|
21
|
+
|
18
22
|
super
|
19
23
|
end
|
20
24
|
|
21
|
-
def self.valid?(
|
22
|
-
|
23
|
-
(
|
24
|
-
|
25
|
+
def self.valid?(name)
|
26
|
+
name.size <= 255 &&
|
27
|
+
(name =~ /\A:[A-Za-z0-9_-]+(\.[A-Za-z0-9_-]+)+\z/ ||
|
28
|
+
name =~ /\A[A-Za-z_-][A-Za-z0-9_-]*(\.[A-Za-z_-][A-Za-z0-9_-]*)+\z/)
|
25
29
|
end
|
26
30
|
end
|
27
31
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
# copied from activesupport/core_ext from Rails, MIT license
|
3
3
|
# https://github.com/rails/rails/tree/9794e85351243cac6d4e78adaba634b8e4ecad0a/activesupport/lib/active_support/core_ext
|
4
4
|
|
5
|
-
|
5
|
+
require_relative "../module/redefine_method"
|
6
6
|
|
7
7
|
class Class
|
8
8
|
# Declare a class-level attribute whose value is inheritable by subclasses.
|