ruby-dbus 0.22.1 → 0.23.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 +13 -0
- data/VERSION +1 -1
- data/doc/Reference.md +4 -4
- data/examples/service/complex-property.rb +2 -2
- data/examples/service/service_newapi.rb +2 -2
- data/lib/dbus/bus.rb +50 -302
- data/lib/dbus/logger.rb +3 -2
- data/lib/dbus/main.rb +66 -0
- data/lib/dbus/message.rb +6 -8
- data/lib/dbus/node_tree.rb +105 -0
- data/lib/dbus/object.rb +16 -7
- data/lib/dbus/object_manager.rb +2 -3
- data/lib/dbus/object_server.rb +119 -0
- data/lib/dbus/proxy_object.rb +4 -4
- data/lib/dbus/proxy_service.rb +95 -0
- data/lib/dbus.rb +9 -8
- data/spec/bus_connection_spec.rb +81 -0
- data/spec/coverage_helper.rb +39 -0
- data/spec/main_loop_spec.rb +14 -0
- data/spec/message_spec.rb +21 -0
- data/spec/mock-service/cockpit-dbustests.rb +29 -0
- data/spec/mock-service/com.redhat.Cockpit.DBusTests.xml +180 -0
- data/spec/mock-service/org.ruby.service.service +4 -0
- data/spec/mock-service/org.rubygems.ruby_dbus.DBusTests.service +4 -0
- data/spec/{service_newapi.rb → mock-service/spaghetti-monster.rb} +22 -10
- data/spec/node_spec.rb +1 -5
- data/spec/object_server_spec.rb +104 -0
- data/spec/object_spec.rb +30 -0
- data/spec/{bus_driver_spec.rb → proxy_service_spec.rb} +1 -1
- data/spec/spec_helper.rb +9 -45
- data/spec/thread_safety_spec.rb +9 -11
- data/spec/tools/dbus-launch-simple +4 -1
- data/spec/tools/test_env +26 -6
- metadata +18 -9
- data/spec/server_spec.rb +0 -55
- data/spec/service_spec.rb +0 -18
- data/spec/tools/test_server +0 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bfebbc3384d221039f465d964817aad4c42ccc147ed6351b23728665c200a9b8
|
4
|
+
data.tar.gz: 63e5542cd3f7a76dc0d7fc0d852e7fae9c0f506fdbc06f7b2d1f644267cead46
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5dea8b83e62b698162f53d18fbc29b60fb594962a449f5d7b8cf82aa10e47fee3633186f894b6d95a42b1d02bc6f5ef172809405e93f57c2b04b450f1fb85732
|
7
|
+
data.tar.gz: 3f0de7019ee46470c4e4afc2f37b4badeab5a1387c6d14c1df2b42b271c7bec9656dad656227e71efdf84d678c88b3394904f2e3c810270aaf0bafdb673fe5c3
|
data/NEWS.md
CHANGED
@@ -2,6 +2,19 @@
|
|
2
2
|
|
3
3
|
## Unreleased
|
4
4
|
|
5
|
+
## Ruby D-Bus 0.23.0.beta1 - 2023-06-05
|
6
|
+
|
7
|
+
Bug fixes:
|
8
|
+
* A service can now have more than one name ([#69][]).
|
9
|
+
Connection#request_service is deprecated in favor of Connection#object_server
|
10
|
+
and BusConnection#request_name
|
11
|
+
|
12
|
+
[#69]: https://github.com/mvidner/ruby-dbus/issues/69
|
13
|
+
|
14
|
+
API:
|
15
|
+
* Remove Service, splitting it into ProxyService and ObjectServer
|
16
|
+
* Split off BusConnection from Connection
|
17
|
+
|
5
18
|
## Ruby D-Bus 0.22.1 - 2023-05-17
|
6
19
|
|
7
20
|
Bug fixes:
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.23.0.beta1
|
data/doc/Reference.md
CHANGED
@@ -24,7 +24,7 @@ is simply "dbus"
|
|
24
24
|
|
25
25
|
1. {DBus.session_bus Connect to the session bus};
|
26
26
|
2. {DBus::Connection#[] get the screensaver service}
|
27
|
-
3. {DBus::
|
27
|
+
3. {DBus::ProxyService#[] and its screensaver object}.
|
28
28
|
4. Call one of its methods in a loop, solving [xkcd#196](http://xkcd.com/196).
|
29
29
|
|
30
30
|
|
@@ -58,7 +58,7 @@ a method proxy always returned an array of values. This was to
|
|
58
58
|
accomodate the rare cases of a DBus method specifying more than one
|
59
59
|
*out* parameter. For compatibility, the behavior is preserved if you
|
60
60
|
construct a {DBus::ProxyObject} with {DBus::ApiOptions::A0},
|
61
|
-
which is what {DBus::
|
61
|
+
which is what {DBus::ProxyService#object} does.
|
62
62
|
|
63
63
|
For nearly all methods you used `Method[0]` or
|
64
64
|
`Method.first`
|
@@ -340,8 +340,8 @@ for overriding this.
|
|
340
340
|
obj = Note.new("/net/vidner/Example/Properties")
|
341
341
|
|
342
342
|
bus = DBus::SessionBus.instance
|
343
|
-
|
344
|
-
|
343
|
+
bus.object_server.export(obj)
|
344
|
+
bus.request_name("net.vidner.Example")
|
345
345
|
|
346
346
|
main = DBus::Main.new
|
347
347
|
main << bus
|
@@ -16,6 +16,6 @@ class Test < DBus::Object
|
|
16
16
|
end
|
17
17
|
|
18
18
|
bus = DBus::SessionBus.instance
|
19
|
-
|
20
|
-
|
19
|
+
bus.object_server.export(Test.new("/net/vidner/Scratch"))
|
20
|
+
bus.request_name("net.vidner.Scratch")
|
21
21
|
DBus::Main.new.tap { |m| m << bus }.run
|
@@ -31,9 +31,9 @@ class Test < DBus::Object
|
|
31
31
|
end
|
32
32
|
|
33
33
|
bus = DBus::SessionBus.instance
|
34
|
-
service = bus.request_service("org.ruby.service")
|
35
34
|
myobj = Test.new("/org/ruby/MyInstance")
|
36
|
-
|
35
|
+
bus.object_server.export(myobj)
|
36
|
+
bus.request_name("org.ruby.service")
|
37
37
|
|
38
38
|
Thread.new do
|
39
39
|
i = 0
|
data/lib/dbus/bus.rb
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
# This file is part of the ruby-dbus project
|
6
6
|
# Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
|
7
7
|
#
|
8
|
-
# This library is free software; you
|
8
|
+
# This library is free software; you can redistribute it and/or
|
9
9
|
# modify it under the terms of the GNU Lesser General Public
|
10
10
|
# License, version 2.1 as published by the Free Software Foundation.
|
11
11
|
# See the file "COPYING" for the exact licensing terms.
|
@@ -17,233 +17,6 @@ require "singleton"
|
|
17
17
|
#
|
18
18
|
# Module containing all the D-Bus modules and classes.
|
19
19
|
module DBus
|
20
|
-
# This represents a remote service. It should not be instantiated directly
|
21
|
-
# Use {Connection#service}
|
22
|
-
class Service
|
23
|
-
# The service name.
|
24
|
-
attr_reader :name
|
25
|
-
# The bus the service is running on.
|
26
|
-
attr_reader :bus
|
27
|
-
# The service root (FIXME).
|
28
|
-
attr_reader :root
|
29
|
-
|
30
|
-
# Create a new service with a given _name_ on a given _bus_.
|
31
|
-
def initialize(name, bus)
|
32
|
-
@name = BusName.new(name)
|
33
|
-
@bus = bus
|
34
|
-
@root = Node.new("/")
|
35
|
-
end
|
36
|
-
|
37
|
-
# Determine whether the service name already exists.
|
38
|
-
def exists?
|
39
|
-
bus.proxy.ListNames[0].member?(@name)
|
40
|
-
end
|
41
|
-
|
42
|
-
# Perform an introspection on all the objects on the service
|
43
|
-
# (starting recursively from the root).
|
44
|
-
def introspect
|
45
|
-
raise NotImplementedError if block_given?
|
46
|
-
|
47
|
-
rec_introspect(@root, "/")
|
48
|
-
self
|
49
|
-
end
|
50
|
-
|
51
|
-
# Retrieves an object at the given _path_.
|
52
|
-
# @param path [ObjectPath]
|
53
|
-
# @return [ProxyObject]
|
54
|
-
def [](path)
|
55
|
-
object(path, api: ApiOptions::A1)
|
56
|
-
end
|
57
|
-
|
58
|
-
# Retrieves an object at the given _path_
|
59
|
-
# whose methods always return an array.
|
60
|
-
# @param path [ObjectPath]
|
61
|
-
# @param api [ApiOptions]
|
62
|
-
# @return [ProxyObject]
|
63
|
-
def object(path, api: ApiOptions::A0)
|
64
|
-
node = get_node(path, create: true)
|
65
|
-
if node.object.nil? || node.object.api != api
|
66
|
-
node.object = ProxyObject.new(
|
67
|
-
@bus, @name, path,
|
68
|
-
api: api
|
69
|
-
)
|
70
|
-
end
|
71
|
-
node.object
|
72
|
-
end
|
73
|
-
|
74
|
-
# Export an object
|
75
|
-
# @param obj [DBus::Object]
|
76
|
-
def export(obj)
|
77
|
-
obj.service = self
|
78
|
-
get_node(obj.path, create: true).object = obj
|
79
|
-
object_manager_for(obj)&.object_added(obj)
|
80
|
-
end
|
81
|
-
|
82
|
-
# Undo exporting an object _obj_.
|
83
|
-
# Raises ArgumentError if it is not a DBus::Object.
|
84
|
-
# Returns the object, or false if _obj_ was not exported.
|
85
|
-
# @param obj [DBus::Object]
|
86
|
-
def unexport(obj)
|
87
|
-
raise ArgumentError, "DBus::Service#unexport() expects a DBus::Object argument" unless obj.is_a?(DBus::Object)
|
88
|
-
return false unless obj.path
|
89
|
-
|
90
|
-
last_path_separator_idx = obj.path.rindex("/")
|
91
|
-
parent_path = obj.path[1..last_path_separator_idx - 1]
|
92
|
-
node_name = obj.path[last_path_separator_idx + 1..-1]
|
93
|
-
|
94
|
-
parent_node = get_node(parent_path, create: false)
|
95
|
-
return false unless parent_node
|
96
|
-
|
97
|
-
object_manager_for(obj)&.object_removed(obj)
|
98
|
-
obj.service = nil
|
99
|
-
parent_node.delete(node_name).object
|
100
|
-
end
|
101
|
-
|
102
|
-
# Get the object node corresponding to the given *path*.
|
103
|
-
# @param path [ObjectPath]
|
104
|
-
# @param create [Boolean] if true, the the {Node}s in the path are created
|
105
|
-
# if they do not already exist.
|
106
|
-
# @return [Node,nil]
|
107
|
-
def get_node(path, create: false)
|
108
|
-
n = @root
|
109
|
-
path.sub(%r{^/}, "").split("/").each do |elem|
|
110
|
-
if !(n[elem])
|
111
|
-
return nil if !create
|
112
|
-
|
113
|
-
n[elem] = Node.new(elem)
|
114
|
-
end
|
115
|
-
n = n[elem]
|
116
|
-
end
|
117
|
-
n
|
118
|
-
end
|
119
|
-
|
120
|
-
# Find the (closest) parent of *object*
|
121
|
-
# implementing the ObjectManager interface, or nil
|
122
|
-
# @return [DBus::Object,nil]
|
123
|
-
def object_manager_for(object)
|
124
|
-
path = object.path
|
125
|
-
node_chain = get_node_chain(path)
|
126
|
-
om_node = node_chain.reverse_each.find do |node|
|
127
|
-
node.object&.is_a? DBus::ObjectManager
|
128
|
-
end
|
129
|
-
om_node&.object
|
130
|
-
end
|
131
|
-
|
132
|
-
# All objects (not paths) under this path (except itself).
|
133
|
-
# @param path [ObjectPath]
|
134
|
-
# @return [Array<DBus::Object>]
|
135
|
-
# @raise ArgumentError if the *path* does not exist
|
136
|
-
def descendants_for(path)
|
137
|
-
node = get_node(path, create: false)
|
138
|
-
raise ArgumentError, "Object path #{path} doesn't exist" if node.nil?
|
139
|
-
|
140
|
-
node.descendant_objects
|
141
|
-
end
|
142
|
-
|
143
|
-
#########
|
144
|
-
|
145
|
-
private
|
146
|
-
|
147
|
-
#########
|
148
|
-
|
149
|
-
# @raise ArgumentError if the *path* does not exist
|
150
|
-
def get_node_chain(path)
|
151
|
-
n = @root
|
152
|
-
result = [n]
|
153
|
-
path.sub(%r{^/}, "").split("/").each do |elem|
|
154
|
-
n = n[elem]
|
155
|
-
raise ArgumentError, "Object path #{path} doesn't exist" if n.nil?
|
156
|
-
|
157
|
-
result.push(n)
|
158
|
-
end
|
159
|
-
result
|
160
|
-
end
|
161
|
-
|
162
|
-
# Perform a recursive retrospection on the given current _node_
|
163
|
-
# on the given _path_.
|
164
|
-
def rec_introspect(node, path)
|
165
|
-
xml = bus.introspect_data(@name, path)
|
166
|
-
intfs, subnodes = IntrospectXMLParser.new(xml).parse
|
167
|
-
subnodes.each do |nodename|
|
168
|
-
subnode = node[nodename] = Node.new(nodename)
|
169
|
-
subpath = if path == "/"
|
170
|
-
"/#{nodename}"
|
171
|
-
else
|
172
|
-
"#{path}/#{nodename}"
|
173
|
-
end
|
174
|
-
rec_introspect(subnode, subpath)
|
175
|
-
end
|
176
|
-
return if intfs.empty?
|
177
|
-
|
178
|
-
node.object = ProxyObjectFactory.new(xml, @bus, @name, path).build
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
# = Object path node class
|
183
|
-
#
|
184
|
-
# Class representing a node on an object path.
|
185
|
-
class Node < Hash
|
186
|
-
# @return [DBus::Object,DBus::ProxyObject,nil]
|
187
|
-
# The D-Bus object contained by the node.
|
188
|
-
attr_accessor :object
|
189
|
-
|
190
|
-
# The name of the node.
|
191
|
-
# @return [String] the last component of its object path, or "/"
|
192
|
-
attr_reader :name
|
193
|
-
|
194
|
-
# Create a new node with a given _name_.
|
195
|
-
def initialize(name)
|
196
|
-
super()
|
197
|
-
@name = name
|
198
|
-
@object = nil
|
199
|
-
end
|
200
|
-
|
201
|
-
# Return an XML string representation of the node.
|
202
|
-
# It is shallow, not recursing into subnodes
|
203
|
-
# @param node_opath [String]
|
204
|
-
def to_xml(node_opath)
|
205
|
-
xml = '<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
|
206
|
-
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
207
|
-
'
|
208
|
-
xml += "<node name=\"#{node_opath}\">\n"
|
209
|
-
each_key do |k|
|
210
|
-
xml += " <node name=\"#{k}\" />\n"
|
211
|
-
end
|
212
|
-
@object&.intfs&.each_value do |v|
|
213
|
-
xml += v.to_xml
|
214
|
-
end
|
215
|
-
xml += "</node>"
|
216
|
-
xml
|
217
|
-
end
|
218
|
-
|
219
|
-
# Return inspect information of the node.
|
220
|
-
def inspect
|
221
|
-
# Need something here
|
222
|
-
"<DBus::Node #{sub_inspect}>"
|
223
|
-
end
|
224
|
-
|
225
|
-
# Return instance inspect information, used by Node#inspect.
|
226
|
-
def sub_inspect
|
227
|
-
s = ""
|
228
|
-
if !@object.nil?
|
229
|
-
s += format("%x ", @object.object_id)
|
230
|
-
end
|
231
|
-
contents_sub_inspect = keys
|
232
|
-
.map { |k| "#{k} => #{self[k].sub_inspect}" }
|
233
|
-
.join(",")
|
234
|
-
"#{s}{#{contents_sub_inspect}}"
|
235
|
-
end
|
236
|
-
|
237
|
-
# All objects (not paths) under this path (except itself).
|
238
|
-
# @return [Array<DBus::Object>]
|
239
|
-
def descendant_objects
|
240
|
-
children_objects = values.map(&:object).compact
|
241
|
-
descendants = values.map(&:descendant_objects)
|
242
|
-
flat_descendants = descendants.reduce([], &:+)
|
243
|
-
children_objects + flat_descendants
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
20
|
# FIXME: rename Connection to Bus?
|
248
21
|
|
249
22
|
# D-Bus main connection class
|
@@ -279,6 +52,10 @@ module DBus
|
|
279
52
|
@proxy = nil
|
280
53
|
end
|
281
54
|
|
55
|
+
def object_server
|
56
|
+
@object_server ||= ObjectServer.new(self)
|
57
|
+
end
|
58
|
+
|
282
59
|
# Dispatch all messages that are available in the queue,
|
283
60
|
# but do not block on the queue.
|
284
61
|
# Called by a main loop when something is available in the queue
|
@@ -487,11 +264,23 @@ module DBus
|
|
487
264
|
class NameRequestError < Exception
|
488
265
|
end
|
489
266
|
|
267
|
+
def handle_return_of_request_name(ret, name)
|
268
|
+
details = if ret == REQUEST_NAME_REPLY_IN_QUEUE
|
269
|
+
other = proxy.GetNameOwner(name).first
|
270
|
+
other_creds = proxy.GetConnectionCredentials(other).first
|
271
|
+
"already owned by #{other}, #{other_creds.inspect}"
|
272
|
+
else
|
273
|
+
"error code #{ret}"
|
274
|
+
end
|
275
|
+
raise NameRequestError, "Could not request #{name}, #{details}" unless ret == REQUEST_NAME_REPLY_PRIMARY_OWNER
|
276
|
+
|
277
|
+
ret
|
278
|
+
end
|
279
|
+
|
490
280
|
# Attempt to request a service _name_.
|
491
|
-
#
|
492
|
-
#
|
493
|
-
#
|
494
|
-
# @return [Service]
|
281
|
+
# @raise NameRequestError which cannot really be rescued as it will be raised when dispatching a later call.
|
282
|
+
# @return [ObjectServer]
|
283
|
+
# @deprecated Use {BusConnection#request_name}.
|
495
284
|
def request_service(name)
|
496
285
|
# Use RequestName, but asynchronously!
|
497
286
|
# A synchronous call would not work with service activation, where
|
@@ -501,17 +290,9 @@ module DBus
|
|
501
290
|
# check and report errors first
|
502
291
|
raise rmsg if rmsg.is_a?(Error)
|
503
292
|
|
504
|
-
|
505
|
-
other = proxy.GetNameOwner(name).first
|
506
|
-
other_creds = proxy.GetConnectionCredentials(other).first
|
507
|
-
"already owned by #{other}, #{other_creds.inspect}"
|
508
|
-
else
|
509
|
-
"error code #{r}"
|
510
|
-
end
|
511
|
-
raise NameRequestError, "Could not request #{name}, #{details}" unless r == REQUEST_NAME_REPLY_PRIMARY_OWNER
|
293
|
+
handle_return_of_request_name(r, name)
|
512
294
|
end
|
513
|
-
|
514
|
-
@service
|
295
|
+
object_server
|
515
296
|
end
|
516
297
|
|
517
298
|
# Set up a ProxyObject for the bus itself, since the bus is introspectable.
|
@@ -631,7 +412,7 @@ module DBus
|
|
631
412
|
if msg.path == "/org/freedesktop/DBus"
|
632
413
|
DBus.logger.debug "Got method call on /org/freedesktop/DBus"
|
633
414
|
end
|
634
|
-
node =
|
415
|
+
node = object_server.get_node(msg.path, create: false)
|
635
416
|
# introspect a known path even if there is no object on it
|
636
417
|
if node &&
|
637
418
|
msg.interface == "org.freedesktop.DBus.Introspectable" &&
|
@@ -670,24 +451,23 @@ module DBus
|
|
670
451
|
def service(name)
|
671
452
|
# The service might not exist at this time so we cannot really check
|
672
453
|
# anything
|
673
|
-
|
454
|
+
ProxyService.new(name, self)
|
674
455
|
end
|
675
456
|
alias [] service
|
676
457
|
|
677
458
|
# @api private
|
678
459
|
# Emit a signal event for the given _service_, object _obj_, interface
|
679
460
|
# _intf_ and signal _sig_ with arguments _args_.
|
680
|
-
# @param
|
461
|
+
# @param _service unused
|
681
462
|
# @param obj [DBus::Object]
|
682
463
|
# @param intf [Interface]
|
683
464
|
# @param sig [Signal]
|
684
465
|
# @param args arguments for the signal
|
685
|
-
def emit(
|
466
|
+
def emit(_service, obj, intf, sig, *args)
|
686
467
|
m = Message.new(DBus::Message::SIGNAL)
|
687
468
|
m.path = obj.path
|
688
469
|
m.interface = intf.name
|
689
470
|
m.member = sig.name
|
690
|
-
m.sender = service.name
|
691
471
|
i = 0
|
692
472
|
sig.params.each do |par|
|
693
473
|
m.add_param(par.type, args[i])
|
@@ -710,7 +490,25 @@ module DBus
|
|
710
490
|
@unique_name = rmsg.destination
|
711
491
|
DBus.logger.debug "Got hello reply. Our unique_name is #{@unique_name}"
|
712
492
|
end
|
713
|
-
|
493
|
+
end
|
494
|
+
end
|
495
|
+
|
496
|
+
# A regular Bus {Connection}.
|
497
|
+
# As opposed to a peer connection to a single counterparty with no daemon in between.
|
498
|
+
# FIXME: move the remaining relevant methods from Connection here, but alias the constants
|
499
|
+
class BusConnection < Connection
|
500
|
+
# @param name [BusName] the requested name
|
501
|
+
# @param flags [Integer] TODO: explain and add a better non-numeric API for this
|
502
|
+
# @raise NameRequestError if we could not get the name
|
503
|
+
# @example Usage
|
504
|
+
# bus = DBus.session_bus
|
505
|
+
# bus.object_server.export(DBus::Object.new("/org/example/Test"))
|
506
|
+
# bus.request_name("org.example.Test")
|
507
|
+
# @see https://dbus.freedesktop.org/doc/dbus-specification.html#bus-messages-request-name
|
508
|
+
def request_name(name, flags: 0)
|
509
|
+
name = BusName.new(name)
|
510
|
+
r = proxy.RequestName(name, flags).first
|
511
|
+
handle_return_of_request_name(r, name)
|
714
512
|
end
|
715
513
|
end
|
716
514
|
|
@@ -720,7 +518,7 @@ module DBus
|
|
720
518
|
#
|
721
519
|
# Use SessionBus, the non-singleton ASessionBus is
|
722
520
|
# for the test suite.
|
723
|
-
class ASessionBus <
|
521
|
+
class ASessionBus < BusConnection
|
724
522
|
# Get the the default session bus.
|
725
523
|
def initialize
|
726
524
|
super(self.class.session_bus_address)
|
@@ -771,7 +569,7 @@ module DBus
|
|
771
569
|
#
|
772
570
|
# Use SystemBus, the non-singleton ASystemBus is
|
773
571
|
# for the test suite.
|
774
|
-
class ASystemBus <
|
572
|
+
class ASystemBus < BusConnection
|
775
573
|
# Get the default system bus.
|
776
574
|
def initialize
|
777
575
|
super(self.class.system_bus_address)
|
@@ -794,7 +592,8 @@ module DBus
|
|
794
592
|
#
|
795
593
|
# you'll need to take care about authentification then, more info here:
|
796
594
|
# https://gitlab.com/pangdudu/ruby-dbus/-/blob/master/README.rdoc
|
797
|
-
|
595
|
+
# TODO: keep the name but update the docs
|
596
|
+
class RemoteBus < BusConnection
|
798
597
|
# Get the remote bus.
|
799
598
|
def initialize(socket_name)
|
800
599
|
super(socket_name)
|
@@ -818,55 +617,4 @@ module DBus
|
|
818
617
|
def self.session_bus
|
819
618
|
SessionBus.instance
|
820
619
|
end
|
821
|
-
|
822
|
-
# = Main event loop class.
|
823
|
-
#
|
824
|
-
# Class that takes care of handling message and signal events
|
825
|
-
# asynchronously. *Note:* This is a native implement and therefore does
|
826
|
-
# not integrate with a graphical widget set main loop.
|
827
|
-
class Main
|
828
|
-
# Create a new main event loop.
|
829
|
-
def initialize
|
830
|
-
@buses = {}
|
831
|
-
@quitting = false
|
832
|
-
end
|
833
|
-
|
834
|
-
# Add a _bus_ to the list of buses to watch for events.
|
835
|
-
def <<(bus)
|
836
|
-
@buses[bus.message_queue.socket] = bus
|
837
|
-
end
|
838
|
-
|
839
|
-
# Quit a running main loop, to be used eg. from a signal handler
|
840
|
-
def quit
|
841
|
-
@quitting = true
|
842
|
-
end
|
843
|
-
|
844
|
-
# Run the main loop. This is a blocking call!
|
845
|
-
def run
|
846
|
-
# before blocking, empty the buffers
|
847
|
-
# https://bugzilla.novell.com/show_bug.cgi?id=537401
|
848
|
-
@buses.each_value do |b|
|
849
|
-
while (m = b.message_queue.message_from_buffer_nonblock)
|
850
|
-
b.process(m)
|
851
|
-
end
|
852
|
-
end
|
853
|
-
while !@quitting && !@buses.empty?
|
854
|
-
ready = IO.select(@buses.keys, [], [], 5) # timeout 5 seconds
|
855
|
-
next unless ready # timeout exceeds so continue unless quitting
|
856
|
-
|
857
|
-
ready.first.each do |socket|
|
858
|
-
b = @buses[socket]
|
859
|
-
begin
|
860
|
-
b.message_queue.buffer_from_socket_nonblock
|
861
|
-
rescue EOFError, SystemCallError
|
862
|
-
@buses.delete socket # this bus died
|
863
|
-
next
|
864
|
-
end
|
865
|
-
while (m = b.message_queue.message_from_buffer_nonblock)
|
866
|
-
b.process(m)
|
867
|
-
end
|
868
|
-
end
|
869
|
-
end
|
870
|
-
end
|
871
|
-
end
|
872
620
|
end
|
data/lib/dbus/logger.rb
CHANGED
@@ -17,9 +17,10 @@ module DBus
|
|
17
17
|
# The default one logs to STDERR,
|
18
18
|
# with DEBUG if $DEBUG is set, otherwise INFO.
|
19
19
|
def logger
|
20
|
-
|
20
|
+
if @logger.nil?
|
21
|
+
debug = $DEBUG || ENV["RUBY_DBUS_DEBUG"]
|
21
22
|
@logger = Logger.new($stderr)
|
22
|
-
@logger.level =
|
23
|
+
@logger.level = debug ? Logger::DEBUG : Logger::INFO
|
23
24
|
end
|
24
25
|
@logger
|
25
26
|
end
|
data/lib/dbus/main.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This file is part of the ruby-dbus project
|
4
|
+
# Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
|
5
|
+
# Copyright (C) 2023 Martin Vidner
|
6
|
+
#
|
7
|
+
# This library is free software; you can redistribute it and/or
|
8
|
+
# modify it under the terms of the GNU Lesser General Public
|
9
|
+
# License, version 2.1 as published by the Free Software Foundation.
|
10
|
+
# See the file "COPYING" for the exact licensing terms.
|
11
|
+
|
12
|
+
module DBus
|
13
|
+
# = Main event loop class.
|
14
|
+
#
|
15
|
+
# Class that takes care of handling message and signal events
|
16
|
+
# asynchronously. *Note:* This is a native implement and therefore does
|
17
|
+
# not integrate with a graphical widget set main loop.
|
18
|
+
class Main
|
19
|
+
# Create a new main event loop.
|
20
|
+
def initialize
|
21
|
+
@buses = {}
|
22
|
+
@quitting = false
|
23
|
+
end
|
24
|
+
|
25
|
+
# Add a _bus_ to the list of buses to watch for events.
|
26
|
+
def <<(bus)
|
27
|
+
@buses[bus.message_queue.socket] = bus
|
28
|
+
end
|
29
|
+
|
30
|
+
# Quit a running main loop, to be used eg. from a signal handler
|
31
|
+
def quit
|
32
|
+
@quitting = true
|
33
|
+
end
|
34
|
+
|
35
|
+
# Run the main loop. This is a blocking call!
|
36
|
+
def run
|
37
|
+
# before blocking, empty the buffers
|
38
|
+
# https://bugzilla.novell.com/show_bug.cgi?id=537401
|
39
|
+
@buses.each_value do |b|
|
40
|
+
while (m = b.message_queue.message_from_buffer_nonblock)
|
41
|
+
b.process(m)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
while !@quitting && !@buses.empty?
|
45
|
+
ready = IO.select(@buses.keys, [], [], 5) # timeout 5 seconds
|
46
|
+
next unless ready # timeout exceeds so continue unless quitting
|
47
|
+
|
48
|
+
ready.first.each do |socket|
|
49
|
+
b = @buses[socket]
|
50
|
+
begin
|
51
|
+
b.message_queue.buffer_from_socket_nonblock
|
52
|
+
rescue EOFError, SystemCallError => e
|
53
|
+
DBus.logger.debug "Got #{e.inspect} from #{socket.inspect}"
|
54
|
+
@buses.delete socket # this bus died
|
55
|
+
next
|
56
|
+
end
|
57
|
+
while (m = b.message_queue.message_from_buffer_nonblock)
|
58
|
+
b.process(m)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
DBus.logger.debug "Main loop quit" if @quitting
|
63
|
+
DBus.logger.debug "Main loop quit, no connections left" if @buses.empty?
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/dbus/message.rb
CHANGED
@@ -16,12 +16,6 @@ require_relative "raw_message"
|
|
16
16
|
#
|
17
17
|
# Module containing all the D-Bus modules and classes.
|
18
18
|
module DBus
|
19
|
-
# = InvalidDestinationName class
|
20
|
-
# Thrown when you try to send a message to /org/freedesktop/DBus/Local, that
|
21
|
-
# is reserved.
|
22
|
-
class InvalidDestinationName < Exception
|
23
|
-
end
|
24
|
-
|
25
19
|
# = D-Bus message class
|
26
20
|
#
|
27
21
|
# Class that holds any type of message that travels over the bus.
|
@@ -164,11 +158,15 @@ module DBus
|
|
164
158
|
SENDER = 7
|
165
159
|
SIGNATURE = 8
|
166
160
|
|
161
|
+
RESERVED_PATH = "/org/freedesktop/DBus/Local"
|
162
|
+
|
167
163
|
# Marshall the message with its current set parameters and return
|
168
164
|
# it in a packet form.
|
165
|
+
# @return [String]
|
169
166
|
def marshall
|
170
|
-
if @path ==
|
171
|
-
|
167
|
+
if @path == RESERVED_PATH
|
168
|
+
# the bus would disconnect us, better explain why
|
169
|
+
raise "Cannot send a message with the reserved path #{RESERVED_PATH}: #{inspect}"
|
172
170
|
end
|
173
171
|
|
174
172
|
params_marshaller = PacketMarshaller.new(endianness: ENDIANNESS)
|