ruby-dbus 0.17.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.
- checksums.yaml +4 -4
- data/NEWS.md +15 -0
- data/README.md +1 -1
- data/Rakefile +3 -11
- data/VERSION +1 -1
- data/doc/Reference.md +9 -2
- data/examples/doc/_extract_examples +2 -0
- data/examples/gdbus/gdbus +11 -5
- 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 +1 -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 +12 -7
- data/lib/dbus/bus.rb +114 -70
- data/lib/dbus/bus_name.rb +12 -8
- data/lib/dbus/error.rb +4 -2
- data/lib/dbus/introspect.rb +29 -18
- data/lib/dbus/logger.rb +3 -1
- data/lib/dbus/marshall.rb +118 -86
- data/lib/dbus/matchrule.rb +16 -16
- data/lib/dbus/message.rb +40 -27
- data/lib/dbus/message_queue.rb +10 -5
- data/lib/dbus/object.rb +34 -13
- data/lib/dbus/object_path.rb +9 -5
- data/lib/dbus/proxy_object.rb +18 -4
- data/lib/dbus/proxy_object_factory.rb +11 -7
- data/lib/dbus/proxy_object_interface.rb +26 -22
- data/lib/dbus/type.rb +41 -34
- data/lib/dbus/xml.rb +28 -17
- data/lib/dbus.rb +7 -7
- data/ruby-dbus.gemspec +4 -2
- 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/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 +2 -0
- data/spec/node_spec.rb +23 -0
- data/spec/object_path_spec.rb +2 -0
- data/spec/property_spec.rb +11 -2
- 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 +19 -4
- data/spec/session_bus_spec.rb +3 -1
- data/spec/session_bus_spec_manual.rb +2 -0
- data/spec/signal_spec.rb +2 -0
- data/spec/spec_helper.rb +5 -3
- data/spec/thread_safety_spec.rb +2 -0
- data/spec/type_spec.rb +2 -0
- data/spec/value_spec.rb +16 -1
- data/spec/variant_spec.rb +4 -2
- metadata +8 -7
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
|
@@ -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,13 +148,17 @@ 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
|
@@ -157,14 +174,12 @@ module DBus
|
|
157
174
|
each_pair do |k, _v|
|
158
175
|
xml += " <node name=\"#{k}\" />\n"
|
159
176
|
end
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
xml += " </interface>\n"
|
167
|
-
end
|
177
|
+
@object&.intfs&.each_pair do |_k, v|
|
178
|
+
xml += " <interface name=\"#{v.name}\">\n"
|
179
|
+
v.methods.each_value { |m| xml += m.to_xml }
|
180
|
+
v.signals.each_value { |m| xml += m.to_xml }
|
181
|
+
v.properties.each_value { |m| xml += m.to_xml }
|
182
|
+
xml += " </interface>\n"
|
168
183
|
end
|
169
184
|
xml += "</node>"
|
170
185
|
xml
|
@@ -182,9 +197,12 @@ module DBus
|
|
182
197
|
if !@object.nil?
|
183
198
|
s += format("%x ", @object.object_id)
|
184
199
|
end
|
185
|
-
|
200
|
+
contents_sub_inspect = keys
|
201
|
+
.map { |k| "#{k} => #{self[k].sub_inspect}" }
|
202
|
+
.join(",")
|
203
|
+
"#{s}{#{contents_sub_inspect}}"
|
186
204
|
end
|
187
|
-
end
|
205
|
+
end
|
188
206
|
|
189
207
|
# FIXME: rename Connection to Bus?
|
190
208
|
|
@@ -207,7 +225,15 @@ module DBus
|
|
207
225
|
def initialize(path)
|
208
226
|
@message_queue = MessageQueue.new(path)
|
209
227
|
@unique_name = nil
|
228
|
+
|
229
|
+
# @return [Hash{Integer => Proc}]
|
230
|
+
# key: message serial
|
231
|
+
# value: block to be run when the reply to that message is received
|
210
232
|
@method_call_replies = {}
|
233
|
+
|
234
|
+
# @return [Hash{Integer => Message}]
|
235
|
+
# for debugging only: messages for which a reply was not received yet;
|
236
|
+
# key == value.serial
|
211
237
|
@method_call_msgs = {}
|
212
238
|
@signal_matchrules = {}
|
213
239
|
@proxy = nil
|
@@ -218,7 +244,7 @@ module DBus
|
|
218
244
|
# but do not block on the queue.
|
219
245
|
# Called by a main loop when something is available in the queue
|
220
246
|
def dispatch_message_queue
|
221
|
-
while (msg = @message_queue.pop(:
|
247
|
+
while (msg = @message_queue.pop(blocking: false)) # FIXME: EOFError
|
222
248
|
process(msg)
|
223
249
|
end
|
224
250
|
end
|
@@ -325,7 +351,7 @@ module DBus
|
|
325
351
|
</signal>
|
326
352
|
</interface>
|
327
353
|
</node>
|
328
|
-
'
|
354
|
+
'
|
329
355
|
# This apostroph is for syntax highlighting editors confused by above xml: "
|
330
356
|
|
331
357
|
# @api private
|
@@ -340,6 +366,7 @@ module DBus
|
|
340
366
|
if reply_handler.nil?
|
341
367
|
send_sync(message) do |rmsg|
|
342
368
|
raise rmsg if rmsg.is_a?(Error)
|
369
|
+
|
343
370
|
ret = rmsg.params
|
344
371
|
end
|
345
372
|
else
|
@@ -444,44 +471,52 @@ module DBus
|
|
444
471
|
end
|
445
472
|
|
446
473
|
# @api private
|
447
|
-
# Send a message
|
474
|
+
# Send a message _msg_ on to the bus. This is done synchronously, thus
|
448
475
|
# the call will block until a reply message arrives.
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
476
|
+
# @param msg [Message]
|
477
|
+
# @param retc [Proc] the reply handler
|
478
|
+
# @yieldparam rmsg [MethodReturnMessage] the reply
|
479
|
+
# @yieldreturn [Array<Object>] the reply (out) parameters
|
480
|
+
def send_sync(msg, &retc) # :yields: reply/return message
|
481
|
+
return if msg.nil? # check if somethings wrong
|
482
|
+
|
483
|
+
@message_queue.push(msg)
|
484
|
+
@method_call_msgs[msg.serial] = msg
|
485
|
+
@method_call_replies[msg.serial] = retc
|
454
486
|
|
455
487
|
retm = wait_for_message
|
456
488
|
return if retm.nil? # check if somethings wrong
|
457
489
|
|
458
490
|
process(retm)
|
459
|
-
while @method_call_replies.key?
|
491
|
+
while @method_call_replies.key? msg.serial
|
460
492
|
retm = wait_for_message
|
461
493
|
process(retm)
|
462
494
|
end
|
463
495
|
rescue EOFError
|
464
|
-
new_err = DBus::Error.new("Connection dropped after we sent #{
|
496
|
+
new_err = DBus::Error.new("Connection dropped after we sent #{msg.inspect}")
|
465
497
|
raise new_err
|
466
498
|
end
|
467
499
|
|
468
500
|
# @api private
|
469
501
|
# Specify a code block that has to be executed when a reply for
|
470
|
-
# message
|
471
|
-
|
502
|
+
# message _msg_ is received.
|
503
|
+
# @param msg [Message]
|
504
|
+
def on_return(msg, &retc)
|
472
505
|
# Have a better exception here
|
473
|
-
if
|
506
|
+
if msg.message_type != Message::METHOD_CALL
|
474
507
|
raise "on_return should only get method_calls"
|
475
508
|
end
|
476
|
-
|
477
|
-
@
|
509
|
+
|
510
|
+
@method_call_msgs[msg.serial] = msg
|
511
|
+
@method_call_replies[msg.serial] = retc
|
478
512
|
end
|
479
513
|
|
480
514
|
# Asks bus to send us messages matching mr, and execute slot when
|
481
515
|
# received
|
482
|
-
|
516
|
+
# @param match_rule [MatchRule,#to_s]
|
517
|
+
def add_match(match_rule, &slot)
|
483
518
|
# check this is a signal.
|
484
|
-
mrs =
|
519
|
+
mrs = match_rule.to_s
|
485
520
|
DBus.logger.debug "#{@signal_matchrules.size} rules, adding #{mrs.inspect}"
|
486
521
|
# don't ask for the same match if we override it
|
487
522
|
unless @signal_matchrules.key?(mrs)
|
@@ -491,70 +526,77 @@ module DBus
|
|
491
526
|
@signal_matchrules[mrs] = slot
|
492
527
|
end
|
493
528
|
|
494
|
-
|
495
|
-
|
529
|
+
# @param match_rule [MatchRule,#to_s]
|
530
|
+
def remove_match(match_rule)
|
531
|
+
mrs = match_rule.to_s
|
496
532
|
rule_existed = @signal_matchrules.delete(mrs).nil?
|
497
533
|
# don't remove nonexisting matches.
|
498
534
|
return if rule_existed
|
535
|
+
|
499
536
|
# FIXME: if we do try, the Error.MatchRuleNotFound is *not* raised
|
500
537
|
# and instead is reported as "no return code for nil"
|
501
538
|
proxy.RemoveMatch(mrs)
|
502
539
|
end
|
503
540
|
|
504
541
|
# @api private
|
505
|
-
# Process a message
|
506
|
-
|
507
|
-
|
508
|
-
|
542
|
+
# Process a message _msg_ based on its type.
|
543
|
+
# @param msg [Message]
|
544
|
+
def process(msg)
|
545
|
+
return if msg.nil? # check if somethings wrong
|
546
|
+
|
547
|
+
case msg.message_type
|
509
548
|
when Message::ERROR, Message::METHOD_RETURN
|
510
|
-
raise InvalidPacketException if
|
511
|
-
|
549
|
+
raise InvalidPacketException if msg.reply_serial.nil?
|
550
|
+
|
551
|
+
mcs = @method_call_replies[msg.reply_serial]
|
512
552
|
if !mcs
|
513
|
-
DBus.logger.debug "no return code for mcs: #{mcs.inspect}
|
553
|
+
DBus.logger.debug "no return code for mcs: #{mcs.inspect} msg: #{msg.inspect}"
|
514
554
|
else
|
515
|
-
if
|
516
|
-
mcs.call(Error.new(
|
555
|
+
if msg.message_type == Message::ERROR
|
556
|
+
mcs.call(Error.new(msg))
|
517
557
|
else
|
518
|
-
mcs.call(
|
558
|
+
mcs.call(msg)
|
519
559
|
end
|
520
|
-
@method_call_replies.delete(
|
521
|
-
@method_call_msgs.delete(
|
560
|
+
@method_call_replies.delete(msg.reply_serial)
|
561
|
+
@method_call_msgs.delete(msg.reply_serial)
|
522
562
|
end
|
523
563
|
when DBus::Message::METHOD_CALL
|
524
|
-
if
|
564
|
+
if msg.path == "/org/freedesktop/DBus"
|
525
565
|
DBus.logger.debug "Got method call on /org/freedesktop/DBus"
|
526
566
|
end
|
527
|
-
node = @service.get_node(
|
567
|
+
node = @service.get_node(msg.path, create: false)
|
528
568
|
if !node
|
529
|
-
reply = Message.error(
|
530
|
-
"Object #{
|
569
|
+
reply = Message.error(msg, "org.freedesktop.DBus.Error.UnknownObject",
|
570
|
+
"Object #{msg.path} doesn't exist")
|
531
571
|
@message_queue.push(reply)
|
532
572
|
# handle introspectable as an exception:
|
533
|
-
elsif
|
534
|
-
|
535
|
-
reply = Message.new(Message::METHOD_RETURN).reply_to(
|
573
|
+
elsif msg.interface == "org.freedesktop.DBus.Introspectable" &&
|
574
|
+
msg.member == "Introspect"
|
575
|
+
reply = Message.new(Message::METHOD_RETURN).reply_to(msg)
|
536
576
|
reply.sender = @unique_name
|
537
|
-
xml = node.to_xml(
|
577
|
+
xml = node.to_xml(msg.path)
|
538
578
|
reply.add_param(Type::STRING, xml)
|
539
579
|
@message_queue.push(reply)
|
540
580
|
else
|
541
581
|
obj = node.object
|
542
582
|
return if obj.nil? # FIXME, pushes no reply
|
543
|
-
|
583
|
+
|
584
|
+
obj&.dispatch(msg)
|
544
585
|
end
|
545
586
|
when DBus::Message::SIGNAL
|
546
587
|
# the signal can match multiple different rules
|
547
588
|
# clone to allow new signale handlers to be registered
|
548
589
|
@signal_matchrules.dup.each do |mrs, slot|
|
549
|
-
if DBus::MatchRule.new.from_s(mrs).match(
|
550
|
-
slot.call(
|
590
|
+
if DBus::MatchRule.new.from_s(mrs).match(msg)
|
591
|
+
slot.call(msg)
|
551
592
|
end
|
552
593
|
end
|
553
594
|
else
|
554
|
-
|
595
|
+
# spec(Message Format): Unknown types must be ignored.
|
596
|
+
DBus.logger.debug "Unknown message type: #{msg.message_type}"
|
555
597
|
end
|
556
|
-
rescue Exception =>
|
557
|
-
raise
|
598
|
+
rescue Exception => e
|
599
|
+
raise msg.annotate_exception(e)
|
558
600
|
end
|
559
601
|
|
560
602
|
# Retrieves the Service with the given _name_.
|
@@ -604,7 +646,7 @@ module DBus
|
|
604
646
|
end
|
605
647
|
@service = Service.new(@unique_name, self)
|
606
648
|
end
|
607
|
-
end
|
649
|
+
end
|
608
650
|
|
609
651
|
# = D-Bus session bus class
|
610
652
|
#
|
@@ -630,6 +672,7 @@ module DBus
|
|
630
672
|
# traditional dbus uses /var/lib/dbus/machine-id
|
631
673
|
machine_id_path = Dir["{/etc,/var/lib/dbus,/var/db/dbus}/machine-id"].first
|
632
674
|
return nil unless machine_id_path
|
675
|
+
|
633
676
|
machine_id = File.read(machine_id_path).chomp
|
634
677
|
|
635
678
|
display = ENV["DISPLAY"][/:(\d+)\.?/, 1]
|
@@ -661,7 +704,7 @@ module DBus
|
|
661
704
|
class ASystemBus < Connection
|
662
705
|
# Get the default system bus.
|
663
706
|
def initialize
|
664
|
-
super(
|
707
|
+
super(SYSTEM_BUS_ADDRESS)
|
665
708
|
send_hello
|
666
709
|
end
|
667
710
|
end
|
@@ -736,6 +779,7 @@ module DBus
|
|
736
779
|
while !@quitting && !@buses.empty?
|
737
780
|
ready = IO.select(@buses.keys, [], [], 5) # timeout 5 seconds
|
738
781
|
next unless ready # timeout exceeds so continue unless quitting
|
782
|
+
|
739
783
|
ready.first.each do |socket|
|
740
784
|
b = @buses[socket]
|
741
785
|
begin
|
@@ -750,5 +794,5 @@ module DBus
|
|
750
794
|
end
|
751
795
|
end
|
752
796
|
end
|
753
|
-
end
|
754
|
-
end
|
797
|
+
end
|
798
|
+
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
|
data/lib/dbus/error.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# error.rb
|
2
4
|
#
|
3
5
|
# This file is part of the ruby-dbus project
|
@@ -32,7 +34,7 @@ module DBus
|
|
32
34
|
end
|
33
35
|
# TODO: validate error name
|
34
36
|
end
|
35
|
-
end
|
37
|
+
end
|
36
38
|
|
37
39
|
# @example raise a generic error
|
38
40
|
# raise DBus.error, "message"
|
@@ -43,4 +45,4 @@ module DBus
|
|
43
45
|
DBus::Error.new(nil, name)
|
44
46
|
end
|
45
47
|
module_function :error
|
46
|
-
end
|
48
|
+
end
|
data/lib/dbus/introspect.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# dbus/introspection.rb - module containing a low-level D-Bus introspection implementation
|
2
4
|
#
|
3
5
|
# This file is part of the ruby-dbus project
|
@@ -10,9 +12,9 @@
|
|
10
12
|
|
11
13
|
module DBus
|
12
14
|
# Regular expressions that should match all method names.
|
13
|
-
METHOD_SIGNAL_RE = /^[A-Za-z][A-Za-z0-9_]
|
15
|
+
METHOD_SIGNAL_RE = /^[A-Za-z][A-Za-z0-9_]*$/.freeze
|
14
16
|
# Regular expressions that should match all interface names.
|
15
|
-
INTERFACE_ELEMENT_RE = /^[A-Za-z][A-Za-z0-9_]
|
17
|
+
INTERFACE_ELEMENT_RE = /^[A-Za-z][A-Za-z0-9_]*$/.freeze
|
16
18
|
|
17
19
|
# Exception raised when an invalid class definition is encountered.
|
18
20
|
class InvalidClassDefinition < Exception
|
@@ -51,23 +53,25 @@ module DBus
|
|
51
53
|
raise InvalidIntrospectionData if name =~ /^\./ || name =~ /\.$/
|
52
54
|
raise InvalidIntrospectionData if name =~ /\.\./
|
53
55
|
raise InvalidIntrospectionData if name !~ /\./
|
56
|
+
|
54
57
|
name.split(".").each do |element|
|
55
58
|
raise InvalidIntrospectionData if element !~ INTERFACE_ELEMENT_RE
|
56
59
|
end
|
57
60
|
end
|
58
61
|
|
59
|
-
# Add
|
60
|
-
# @param
|
61
|
-
def define(
|
62
|
-
name =
|
63
|
-
category =
|
62
|
+
# Add _ifc_el_ as a known {Method}, {Signal} or {Property}
|
63
|
+
# @param ifc_el [InterfaceElement]
|
64
|
+
def define(ifc_el)
|
65
|
+
name = ifc_el.name.to_sym
|
66
|
+
category = case ifc_el
|
67
|
+
when Method
|
64
68
|
@methods
|
65
|
-
|
69
|
+
when Signal
|
66
70
|
@signals
|
67
|
-
|
71
|
+
when Property
|
68
72
|
@properties
|
69
73
|
end
|
70
|
-
category[name] =
|
74
|
+
category[name] = ifc_el
|
71
75
|
end
|
72
76
|
alias declare define
|
73
77
|
alias << define
|
@@ -81,11 +85,13 @@ module DBus
|
|
81
85
|
define(m)
|
82
86
|
end
|
83
87
|
alias declare_method define_method
|
84
|
-
end
|
88
|
+
end
|
85
89
|
|
86
90
|
# = A formal parameter has a name and a type
|
87
91
|
class FormalParameter
|
92
|
+
# @return [#to_s]
|
88
93
|
attr_reader :name
|
94
|
+
# @return [SingleCompleteType]
|
89
95
|
attr_reader :type
|
90
96
|
|
91
97
|
def initialize(name, type)
|
@@ -107,14 +113,16 @@ module DBus
|
|
107
113
|
# This is a generic class for entities that are part of the interface
|
108
114
|
# such as methods and signals.
|
109
115
|
class InterfaceElement
|
110
|
-
# The name of the interface element
|
116
|
+
# @return [Symbol] The name of the interface element
|
111
117
|
attr_reader :name
|
112
|
-
|
118
|
+
|
119
|
+
# @return [Array<FormalParameter>] The parameters of the interface element
|
113
120
|
attr_reader :params
|
114
121
|
|
115
122
|
# Validates element _name_.
|
116
123
|
def validate_name(name)
|
117
124
|
return if (name =~ METHOD_SIGNAL_RE) && (name.bytesize <= 255)
|
125
|
+
|
118
126
|
raise InvalidMethodName, name
|
119
127
|
end
|
120
128
|
|
@@ -135,13 +143,13 @@ module DBus
|
|
135
143
|
def add_param(name_signature_pair)
|
136
144
|
add_fparam(*name_signature_pair)
|
137
145
|
end
|
138
|
-
end
|
146
|
+
end
|
139
147
|
|
140
148
|
# = D-Bus interface method class
|
141
149
|
#
|
142
150
|
# This is a class representing methods that are part of an interface.
|
143
151
|
class Method < InterfaceElement
|
144
|
-
# The list of return values for the method
|
152
|
+
# @return [Array<FormalParameter>] The list of return values for the method
|
145
153
|
attr_reader :rets
|
146
154
|
|
147
155
|
# Creates a new method interface element with the given _name_.
|
@@ -151,6 +159,8 @@ module DBus
|
|
151
159
|
end
|
152
160
|
|
153
161
|
# Add a return value _name_ and _signature_.
|
162
|
+
# @param name [#to_s]
|
163
|
+
# @param signature [SingleCompleteType]
|
154
164
|
def add_return(name, signature)
|
155
165
|
@rets << FormalParameter.new(name, signature)
|
156
166
|
end
|
@@ -161,6 +171,7 @@ module DBus
|
|
161
171
|
prototype.split(/, */).each do |arg|
|
162
172
|
arg = arg.split(" ")
|
163
173
|
raise InvalidClassDefinition if arg.size != 2
|
174
|
+
|
164
175
|
dir, arg = arg
|
165
176
|
if arg =~ /:/
|
166
177
|
arg = arg.split(":")
|
@@ -192,7 +203,7 @@ module DBus
|
|
192
203
|
xml += " </method>\n"
|
193
204
|
xml
|
194
205
|
end
|
195
|
-
end
|
206
|
+
end
|
196
207
|
|
197
208
|
# = D-Bus interface signal class
|
198
209
|
#
|
@@ -222,7 +233,7 @@ module DBus
|
|
222
233
|
xml += " </signal>\n"
|
223
234
|
xml
|
224
235
|
end
|
225
|
-
end
|
236
|
+
end
|
226
237
|
|
227
238
|
# An (exported) property
|
228
239
|
# https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties
|
@@ -259,4 +270,4 @@ module DBus
|
|
259
270
|
" <property type=\"#{@type}\" name=\"#{@name}\" access=\"#{@access}\"/>\n"
|
260
271
|
end
|
261
272
|
end
|
262
|
-
end
|
273
|
+
end
|
data/lib/dbus/logger.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# dbus/logger.rb - debug logging
|
2
4
|
#
|
3
5
|
# This file is part of the ruby-dbus project
|
@@ -16,7 +18,7 @@ module DBus
|
|
16
18
|
# with DEBUG if $DEBUG is set, otherwise INFO.
|
17
19
|
def logger
|
18
20
|
unless defined? @logger
|
19
|
-
@logger = Logger.new(
|
21
|
+
@logger = Logger.new($stderr)
|
20
22
|
@logger.level = $DEBUG ? Logger::DEBUG : Logger::INFO
|
21
23
|
end
|
22
24
|
@logger
|