ruby-dbus 0.23.0.beta1 → 0.23.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 +38 -3
- data/VERSION +1 -1
- data/doc/Reference.md +1 -1
- data/examples/no-bus/pulseaudio.rb +50 -0
- data/examples/utils/listnames.rb +9 -1
- data/lib/dbus/bus.rb +125 -432
- data/lib/dbus/connection.rb +363 -0
- data/lib/dbus/object.rb +46 -18
- data/lib/dbus/object_manager.rb +5 -1
- data/lib/dbus/object_server.rb +44 -14
- data/lib/dbus/org.freedesktop.DBus.xml +97 -0
- data/lib/dbus/proxy_service.rb +14 -2
- data/lib/dbus.rb +1 -0
- data/ruby-dbus.gemspec +1 -1
- data/spec/bus_connection_spec.rb +27 -15
- data/spec/connection_spec.rb +37 -0
- data/spec/dbus_spec.rb +22 -0
- data/spec/mock-service/spaghetti-monster.rb +4 -5
- data/spec/object_server_spec.rb +58 -24
- data/spec/object_spec.rb +16 -0
- data/spec/proxy_service_spec.rb +12 -7
- data/spec/tools/dbus-limited-session.conf +3 -0
- metadata +10 -5
data/lib/dbus/bus.rb
CHANGED
@@ -13,286 +13,26 @@
|
|
13
13
|
require "socket"
|
14
14
|
require "singleton"
|
15
15
|
|
16
|
+
require_relative "connection"
|
17
|
+
|
16
18
|
# = D-Bus main module
|
17
19
|
#
|
18
20
|
# Module containing all the D-Bus modules and classes.
|
19
21
|
module DBus
|
20
|
-
#
|
21
|
-
|
22
|
-
|
23
|
-
#
|
24
|
-
# Main class that maintains a connection to a bus and can handle incoming
|
25
|
-
# and outgoing messages.
|
26
|
-
class Connection
|
22
|
+
# A regular Bus {Connection}.
|
23
|
+
# As opposed to a peer connection to a single counterparty with no daemon in between.
|
24
|
+
class BusConnection < Connection
|
27
25
|
# The unique name (by specification) of the message.
|
28
26
|
attr_reader :unique_name
|
29
|
-
# pop and push messages here
|
30
|
-
attr_reader :message_queue
|
31
|
-
|
32
|
-
# Create a new connection to the bus for a given connect _path_. _path_
|
33
|
-
# format is described in the D-Bus specification:
|
34
|
-
# http://dbus.freedesktop.org/doc/dbus-specification.html#addresses
|
35
|
-
# and is something like:
|
36
|
-
# "transport1:key1=value1,key2=value2;transport2:key1=value1,key2=value2"
|
37
|
-
# e.g. "unix:path=/tmp/dbus-test" or "tcp:host=localhost,port=2687"
|
38
|
-
def initialize(path)
|
39
|
-
@message_queue = MessageQueue.new(path)
|
40
|
-
@unique_name = nil
|
41
|
-
|
42
|
-
# @return [Hash{Integer => Proc}]
|
43
|
-
# key: message serial
|
44
|
-
# value: block to be run when the reply to that message is received
|
45
|
-
@method_call_replies = {}
|
46
27
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
28
|
+
# Connect, authenticate, and send Hello.
|
29
|
+
# @param addresses [String]
|
30
|
+
# @see https://dbus.freedesktop.org/doc/dbus-specification.html#addresses
|
31
|
+
def initialize(addresses)
|
32
|
+
super
|
33
|
+
@unique_name = nil
|
52
34
|
@proxy = nil
|
53
|
-
|
54
|
-
|
55
|
-
def object_server
|
56
|
-
@object_server ||= ObjectServer.new(self)
|
57
|
-
end
|
58
|
-
|
59
|
-
# Dispatch all messages that are available in the queue,
|
60
|
-
# but do not block on the queue.
|
61
|
-
# Called by a main loop when something is available in the queue
|
62
|
-
def dispatch_message_queue
|
63
|
-
while (msg = @message_queue.pop(blocking: false)) # FIXME: EOFError
|
64
|
-
process(msg)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
# Tell a bus to register itself on the glib main loop
|
69
|
-
def glibize
|
70
|
-
require "glib2"
|
71
|
-
# Circumvent a ruby-glib bug
|
72
|
-
@channels ||= []
|
73
|
-
|
74
|
-
gio = GLib::IOChannel.new(@message_queue.socket.fileno)
|
75
|
-
@channels << gio
|
76
|
-
gio.add_watch(GLib::IOChannel::IN) do |_c, _ch|
|
77
|
-
dispatch_message_queue
|
78
|
-
true
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
# FIXME: describe the following names, flags and constants.
|
83
|
-
# See DBus spec for definition
|
84
|
-
NAME_FLAG_ALLOW_REPLACEMENT = 0x1
|
85
|
-
NAME_FLAG_REPLACE_EXISTING = 0x2
|
86
|
-
NAME_FLAG_DO_NOT_QUEUE = 0x4
|
87
|
-
|
88
|
-
REQUEST_NAME_REPLY_PRIMARY_OWNER = 0x1
|
89
|
-
REQUEST_NAME_REPLY_IN_QUEUE = 0x2
|
90
|
-
REQUEST_NAME_REPLY_EXISTS = 0x3
|
91
|
-
REQUEST_NAME_REPLY_ALREADY_OWNER = 0x4
|
92
|
-
|
93
|
-
DBUSXMLINTRO = '<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
|
94
|
-
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
95
|
-
<node>
|
96
|
-
<interface name="org.freedesktop.DBus.Introspectable">
|
97
|
-
<method name="Introspect">
|
98
|
-
<arg direction="out" type="s"/>
|
99
|
-
</method>
|
100
|
-
</interface>
|
101
|
-
<interface name="org.freedesktop.DBus">
|
102
|
-
<method name="Hello">
|
103
|
-
<arg direction="out" type="s"/>
|
104
|
-
</method>
|
105
|
-
<method name="RequestName">
|
106
|
-
<arg direction="in" type="s"/>
|
107
|
-
<arg direction="in" type="u"/>
|
108
|
-
<arg direction="out" type="u"/>
|
109
|
-
</method>
|
110
|
-
<method name="ReleaseName">
|
111
|
-
<arg direction="in" type="s"/>
|
112
|
-
<arg direction="out" type="u"/>
|
113
|
-
</method>
|
114
|
-
<method name="StartServiceByName">
|
115
|
-
<arg direction="in" type="s"/>
|
116
|
-
<arg direction="in" type="u"/>
|
117
|
-
<arg direction="out" type="u"/>
|
118
|
-
</method>
|
119
|
-
<method name="UpdateActivationEnvironment">
|
120
|
-
<arg direction="in" type="a{ss}"/>
|
121
|
-
</method>
|
122
|
-
<method name="NameHasOwner">
|
123
|
-
<arg direction="in" type="s"/>
|
124
|
-
<arg direction="out" type="b"/>
|
125
|
-
</method>
|
126
|
-
<method name="ListNames">
|
127
|
-
<arg direction="out" type="as"/>
|
128
|
-
</method>
|
129
|
-
<method name="ListActivatableNames">
|
130
|
-
<arg direction="out" type="as"/>
|
131
|
-
</method>
|
132
|
-
<method name="AddMatch">
|
133
|
-
<arg direction="in" type="s"/>
|
134
|
-
</method>
|
135
|
-
<method name="RemoveMatch">
|
136
|
-
<arg direction="in" type="s"/>
|
137
|
-
</method>
|
138
|
-
<method name="GetNameOwner">
|
139
|
-
<arg direction="in" type="s"/>
|
140
|
-
<arg direction="out" type="s"/>
|
141
|
-
</method>
|
142
|
-
<method name="ListQueuedOwners">
|
143
|
-
<arg direction="in" type="s"/>
|
144
|
-
<arg direction="out" type="as"/>
|
145
|
-
</method>
|
146
|
-
<method name="GetConnectionUnixUser">
|
147
|
-
<arg direction="in" type="s"/>
|
148
|
-
<arg direction="out" type="u"/>
|
149
|
-
</method>
|
150
|
-
<method name="GetConnectionUnixProcessID">
|
151
|
-
<arg direction="in" type="s"/>
|
152
|
-
<arg direction="out" type="u"/>
|
153
|
-
</method>
|
154
|
-
<method name="GetAdtAuditSessionData">
|
155
|
-
<arg direction="in" type="s"/>
|
156
|
-
<arg direction="out" type="ay"/>
|
157
|
-
</method>
|
158
|
-
<method name="GetConnectionSELinuxSecurityContext">
|
159
|
-
<arg direction="in" type="s"/>
|
160
|
-
<arg direction="out" type="ay"/>
|
161
|
-
</method>
|
162
|
-
<method name="ReloadConfig">
|
163
|
-
</method>
|
164
|
-
<method name="GetId">
|
165
|
-
<arg direction="out" type="s"/>
|
166
|
-
</method>
|
167
|
-
<method name="GetConnectionCredentials">
|
168
|
-
<arg direction="in" type="s"/>
|
169
|
-
<arg direction="out" type="a{sv}"/>
|
170
|
-
</method>
|
171
|
-
<property name="Features" type="as" access="read">
|
172
|
-
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
|
173
|
-
</property>
|
174
|
-
<property name="Interfaces" type="as" access="read">
|
175
|
-
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
|
176
|
-
</property>
|
177
|
-
<signal name="NameOwnerChanged">
|
178
|
-
<arg type="s"/>
|
179
|
-
<arg type="s"/>
|
180
|
-
<arg type="s"/>
|
181
|
-
</signal>
|
182
|
-
<signal name="NameLost">
|
183
|
-
<arg type="s"/>
|
184
|
-
</signal>
|
185
|
-
<signal name="NameAcquired">
|
186
|
-
<arg type="s"/>
|
187
|
-
</signal>
|
188
|
-
</interface>
|
189
|
-
</node>
|
190
|
-
'
|
191
|
-
# This apostroph is for syntax highlighting editors confused by above xml: "
|
192
|
-
|
193
|
-
# @api private
|
194
|
-
# Send a _message_.
|
195
|
-
# If _reply_handler_ is not given, wait for the reply
|
196
|
-
# and return the reply, or raise the error.
|
197
|
-
# If _reply_handler_ is given, it will be called when the reply
|
198
|
-
# eventually arrives, with the reply message as the 1st param
|
199
|
-
# and its params following
|
200
|
-
def send_sync_or_async(message, &reply_handler)
|
201
|
-
ret = nil
|
202
|
-
if reply_handler.nil?
|
203
|
-
send_sync(message) do |rmsg|
|
204
|
-
raise rmsg if rmsg.is_a?(Error)
|
205
|
-
|
206
|
-
ret = rmsg.params
|
207
|
-
end
|
208
|
-
else
|
209
|
-
on_return(message) do |rmsg|
|
210
|
-
if rmsg.is_a?(Error)
|
211
|
-
reply_handler.call(rmsg)
|
212
|
-
else
|
213
|
-
reply_handler.call(rmsg, * rmsg.params)
|
214
|
-
end
|
215
|
-
end
|
216
|
-
@message_queue.push(message)
|
217
|
-
end
|
218
|
-
ret
|
219
|
-
end
|
220
|
-
|
221
|
-
# @api private
|
222
|
-
def introspect_data(dest, path, &reply_handler)
|
223
|
-
m = DBus::Message.new(DBus::Message::METHOD_CALL)
|
224
|
-
m.path = path
|
225
|
-
m.interface = "org.freedesktop.DBus.Introspectable"
|
226
|
-
m.destination = dest
|
227
|
-
m.member = "Introspect"
|
228
|
-
m.sender = unique_name
|
229
|
-
if reply_handler.nil?
|
230
|
-
send_sync_or_async(m).first
|
231
|
-
else
|
232
|
-
send_sync_or_async(m) do |*args|
|
233
|
-
# TODO: test async introspection, is it used at all?
|
234
|
-
args.shift # forget the message, pass only the text
|
235
|
-
reply_handler.call(*args)
|
236
|
-
nil
|
237
|
-
end
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
# @api private
|
242
|
-
# Issues a call to the org.freedesktop.DBus.Introspectable.Introspect method
|
243
|
-
# _dest_ is the service and _path_ the object path you want to introspect
|
244
|
-
# If a code block is given, the introspect call in asynchronous. If not
|
245
|
-
# data is returned
|
246
|
-
#
|
247
|
-
# FIXME: link to ProxyObject data definition
|
248
|
-
# The returned object is a ProxyObject that has methods you can call to
|
249
|
-
# issue somme METHOD_CALL messages, and to setup to receive METHOD_RETURN
|
250
|
-
def introspect(dest, path)
|
251
|
-
if !block_given?
|
252
|
-
# introspect in synchronous !
|
253
|
-
data = introspect_data(dest, path)
|
254
|
-
pof = DBus::ProxyObjectFactory.new(data, self, dest, path)
|
255
|
-
pof.build
|
256
|
-
else
|
257
|
-
introspect_data(dest, path) do |async_data|
|
258
|
-
yield(DBus::ProxyObjectFactory.new(async_data, self, dest, path).build)
|
259
|
-
end
|
260
|
-
end
|
261
|
-
end
|
262
|
-
|
263
|
-
# Exception raised when a service name is requested that is not available.
|
264
|
-
class NameRequestError < Exception
|
265
|
-
end
|
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
|
-
|
280
|
-
# Attempt to request a service _name_.
|
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}.
|
284
|
-
def request_service(name)
|
285
|
-
# Use RequestName, but asynchronously!
|
286
|
-
# A synchronous call would not work with service activation, where
|
287
|
-
# method calls to be serviced arrive before the reply for RequestName
|
288
|
-
# (Ticket#29).
|
289
|
-
proxy.RequestName(name, NAME_FLAG_REPLACE_EXISTING) do |rmsg, r|
|
290
|
-
# check and report errors first
|
291
|
-
raise rmsg if rmsg.is_a?(Error)
|
292
|
-
|
293
|
-
handle_return_of_request_name(r, name)
|
294
|
-
end
|
295
|
-
object_server
|
35
|
+
send_hello
|
296
36
|
end
|
297
37
|
|
298
38
|
# Set up a ProxyObject for the bus itself, since the bus is introspectable.
|
@@ -301,10 +41,13 @@ module DBus
|
|
301
41
|
# Returns the object.
|
302
42
|
def proxy
|
303
43
|
if @proxy.nil?
|
44
|
+
xml_filename = File.expand_path("org.freedesktop.DBus.xml", __dir__)
|
45
|
+
xml = File.read(xml_filename)
|
46
|
+
|
304
47
|
path = "/org/freedesktop/DBus"
|
305
48
|
dest = "org.freedesktop.DBus"
|
306
49
|
pof = DBus::ProxyObjectFactory.new(
|
307
|
-
|
50
|
+
xml, self, dest, path,
|
308
51
|
api: ApiOptions::A0
|
309
52
|
)
|
310
53
|
@proxy = pof.build["org.freedesktop.DBus"]
|
@@ -312,72 +55,126 @@ module DBus
|
|
312
55
|
@proxy
|
313
56
|
end
|
314
57
|
|
315
|
-
#
|
316
|
-
#
|
317
|
-
|
318
|
-
|
58
|
+
# Request a well-known name so that clients can find us.
|
59
|
+
# @note Parameters other than *name* are advanced, you probably don't need them.
|
60
|
+
#
|
61
|
+
# With no boolean flags, running a second instance of a program that calls `request_name`
|
62
|
+
# will result in the second one failing, which this library translates to an exception.
|
63
|
+
# If you want the second instance to take over, you need both
|
64
|
+
# `allow_replacement: true` and `replace_existing: true.`
|
65
|
+
#
|
66
|
+
# @param name [BusName] the requested name
|
67
|
+
# @param replace_existing [Boolean]
|
68
|
+
# Replace an existing owner of the name, if that owner set *allow_replacement*.
|
69
|
+
# @param allow_replacement [Boolean]
|
70
|
+
# Other connections that specify *replace_existing* will be able to take
|
71
|
+
# the name from us. We will get {#on_name_lost NameLost}. If we specified *queue*
|
72
|
+
# we may get the name again, with {#on_name_acquired NameAcquired}.
|
73
|
+
# @param queue [Boolean]
|
74
|
+
# Affects the behavior when the bus denies the name (sooner or later).
|
75
|
+
# - If `false` (default), it is recommended to let the `NameRequestError` fall through and end your program.
|
76
|
+
# - If `true`, you should `rescue` the `NameRequestError` and set up
|
77
|
+
# {#on_name_acquired NameAcquired} and {#on_name_lost NameLost} handlers.
|
78
|
+
# Meanwhile, the bus will put us in a queue waiting for *name* (this is the "sooner" case).
|
79
|
+
# Also, if we had `allow_replacement: true`, another connection can cause us
|
80
|
+
# to lose the name. We will be moved back to the queue, waiting for when the other owners give up
|
81
|
+
# (the "later" case).
|
82
|
+
# @param flags [Integer,nil]
|
83
|
+
# If specified, overrides the boolean parameters.
|
84
|
+
# Use a bitwise sum `|` of:
|
85
|
+
# - NAME_FLAG_ALLOW_REPLACEMENT
|
86
|
+
# - NAME_FLAG_REPLACE_EXISTING
|
87
|
+
# - NAME_FLAG_DO_NOT_QUEUE
|
88
|
+
# Note that `0` implies `queue: true`.
|
89
|
+
#
|
90
|
+
# @return [REQUEST_NAME_REPLY_PRIMARY_OWNER,REQUEST_NAME_REPLY_ALREADY_OWNER] on success
|
91
|
+
# @raise [NameRequestError] with #error_code REQUEST_NAME_REPLY_EXISTS or REQUEST_NAME_REPLY_IN_QUEUE, on failure
|
92
|
+
# @raise DBus::Error another way to fail is being prohibited to own the name
|
93
|
+
# which is the default on the system bus
|
94
|
+
#
|
95
|
+
# @see https://dbus.freedesktop.org/doc/dbus-specification.html#bus-messages-request-name
|
96
|
+
#
|
97
|
+
# @example Simple usage
|
98
|
+
# bus = DBus.session_bus
|
99
|
+
# bus.object_server.export(DBus::Object.new("/org/example/Test"))
|
100
|
+
# bus.request_name("org.example.Test")
|
101
|
+
# # main loop
|
102
|
+
#
|
103
|
+
# @example Second instance taking over
|
104
|
+
# bus = DBus.session_bus
|
105
|
+
# bus.object_server.export(DBus::Object.new("/org/example/Test"))
|
106
|
+
# bus.on_name_lost { exit }
|
107
|
+
# bus.request_name("org.example.Test", allow_replacement: true, replace_existing: true)
|
108
|
+
# # main loop
|
109
|
+
#
|
110
|
+
# @example Second instance waiting for its turn
|
111
|
+
# bus = DBus.session_bus
|
112
|
+
# bus.object_server.export(DBus::Object.new("/org/example/Test"))
|
113
|
+
# bus.on_name_acquired { @owner = true }
|
114
|
+
# begin
|
115
|
+
# bus.request_name("org.example.Test", queue: true)
|
116
|
+
# rescue DBus::Connection::NameRequestError => e
|
117
|
+
# @owner = false
|
118
|
+
# end
|
119
|
+
# # main loop
|
120
|
+
def request_name(name,
|
121
|
+
allow_replacement: false,
|
122
|
+
replace_existing: false,
|
123
|
+
queue: false,
|
124
|
+
flags: nil)
|
125
|
+
if flags.nil?
|
126
|
+
flags = (allow_replacement ? NAME_FLAG_ALLOW_REPLACEMENT : 0) |
|
127
|
+
(replace_existing ? NAME_FLAG_REPLACE_EXISTING : 0) |
|
128
|
+
(queue ? 0 : NAME_FLAG_DO_NOT_QUEUE)
|
129
|
+
end
|
130
|
+
name = BusName.new(name)
|
131
|
+
r = proxy.RequestName(name, flags).first
|
132
|
+
handle_return_of_request_name(r, name)
|
319
133
|
end
|
320
134
|
|
321
|
-
#
|
322
|
-
#
|
323
|
-
#
|
324
|
-
#
|
325
|
-
|
326
|
-
#
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
retm = wait_for_message
|
336
|
-
return if retm.nil? # check if somethings wrong
|
337
|
-
|
338
|
-
process(retm)
|
339
|
-
while @method_call_replies.key? msg.serial
|
340
|
-
retm = wait_for_message
|
341
|
-
process(retm)
|
342
|
-
end
|
343
|
-
rescue EOFError
|
344
|
-
new_err = DBus::Error.new("Connection dropped after we sent #{msg.inspect}")
|
345
|
-
raise new_err
|
135
|
+
# The caller has released his claim on the given name.
|
136
|
+
# Either the caller was the primary owner of the name, and the name is now unused
|
137
|
+
# or taken by somebody waiting in the queue for the name,
|
138
|
+
# or the caller was waiting in the queue for the name and has now been removed from the queue.
|
139
|
+
RELEASE_NAME_REPLY_RELEASED = 1
|
140
|
+
# The given name does not exist on this bus.
|
141
|
+
RELEASE_NAME_REPLY_NON_EXISTENT = 2
|
142
|
+
# The caller was not the primary owner of this name, and was also not waiting in the queue to own this name.
|
143
|
+
RELEASE_NAME_REPLY_NOT_OWNER = 3
|
144
|
+
|
145
|
+
# @param name [BusName] the name to release
|
146
|
+
def release_name(name)
|
147
|
+
name = BusName.new(name)
|
148
|
+
proxy.ReleaseName(name).first
|
346
149
|
end
|
347
150
|
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
# @param msg [Message]
|
352
|
-
def on_return(msg, &retc)
|
353
|
-
# Have a better exception here
|
354
|
-
if msg.message_type != Message::METHOD_CALL
|
355
|
-
raise "on_return should only get method_calls"
|
356
|
-
end
|
151
|
+
def on_name_acquired(&handler)
|
152
|
+
proxy.on_signal("NameAcquired", &handler)
|
153
|
+
end
|
357
154
|
|
358
|
-
|
359
|
-
|
155
|
+
def on_name_lost(&handler)
|
156
|
+
proxy.on_signal("NameLost", &handler)
|
360
157
|
end
|
361
158
|
|
362
159
|
# Asks bus to send us messages matching mr, and execute slot when
|
363
160
|
# received
|
364
161
|
# @param match_rule [MatchRule,#to_s]
|
162
|
+
# @return [void]
|
365
163
|
def add_match(match_rule, &slot)
|
366
|
-
# check this is a signal.
|
367
164
|
mrs = match_rule.to_s
|
368
|
-
|
165
|
+
rule_existed = super(mrs, &slot)
|
369
166
|
# don't ask for the same match if we override it
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
@signal_matchrules[mrs] = slot
|
167
|
+
return if rule_existed
|
168
|
+
|
169
|
+
DBus.logger.debug "Asked for a new match"
|
170
|
+
proxy.AddMatch(mrs)
|
375
171
|
end
|
376
172
|
|
377
173
|
# @param match_rule [MatchRule,#to_s]
|
174
|
+
# @return [void]
|
378
175
|
def remove_match(match_rule)
|
379
176
|
mrs = match_rule.to_s
|
380
|
-
rule_existed =
|
177
|
+
rule_existed = super(mrs)
|
381
178
|
# don't remove nonexisting matches.
|
382
179
|
return if rule_existed
|
383
180
|
|
@@ -386,68 +183,10 @@ module DBus
|
|
386
183
|
proxy.RemoveMatch(mrs)
|
387
184
|
end
|
388
185
|
|
389
|
-
#
|
390
|
-
#
|
391
|
-
#
|
392
|
-
|
393
|
-
return if msg.nil? # check if somethings wrong
|
394
|
-
|
395
|
-
case msg.message_type
|
396
|
-
when Message::ERROR, Message::METHOD_RETURN
|
397
|
-
raise InvalidPacketException if msg.reply_serial.nil?
|
398
|
-
|
399
|
-
mcs = @method_call_replies[msg.reply_serial]
|
400
|
-
if !mcs
|
401
|
-
DBus.logger.debug "no return code for mcs: #{mcs.inspect} msg: #{msg.inspect}"
|
402
|
-
else
|
403
|
-
if msg.message_type == Message::ERROR
|
404
|
-
mcs.call(Error.new(msg))
|
405
|
-
else
|
406
|
-
mcs.call(msg)
|
407
|
-
end
|
408
|
-
@method_call_replies.delete(msg.reply_serial)
|
409
|
-
@method_call_msgs.delete(msg.reply_serial)
|
410
|
-
end
|
411
|
-
when DBus::Message::METHOD_CALL
|
412
|
-
if msg.path == "/org/freedesktop/DBus"
|
413
|
-
DBus.logger.debug "Got method call on /org/freedesktop/DBus"
|
414
|
-
end
|
415
|
-
node = object_server.get_node(msg.path, create: false)
|
416
|
-
# introspect a known path even if there is no object on it
|
417
|
-
if node &&
|
418
|
-
msg.interface == "org.freedesktop.DBus.Introspectable" &&
|
419
|
-
msg.member == "Introspect"
|
420
|
-
reply = Message.new(Message::METHOD_RETURN).reply_to(msg)
|
421
|
-
reply.sender = @unique_name
|
422
|
-
xml = node.to_xml(msg.path)
|
423
|
-
reply.add_param(Type::STRING, xml)
|
424
|
-
@message_queue.push(reply)
|
425
|
-
# dispatch for an object
|
426
|
-
elsif node&.object
|
427
|
-
node.object.dispatch(msg)
|
428
|
-
else
|
429
|
-
reply = Message.error(msg, "org.freedesktop.DBus.Error.UnknownObject",
|
430
|
-
"Object #{msg.path} doesn't exist")
|
431
|
-
@message_queue.push(reply)
|
432
|
-
end
|
433
|
-
when DBus::Message::SIGNAL
|
434
|
-
# the signal can match multiple different rules
|
435
|
-
# clone to allow new signale handlers to be registered
|
436
|
-
@signal_matchrules.dup.each do |mrs, slot|
|
437
|
-
if DBus::MatchRule.new.from_s(mrs).match(msg)
|
438
|
-
slot.call(msg)
|
439
|
-
end
|
440
|
-
end
|
441
|
-
else
|
442
|
-
# spec(Message Format): Unknown types must be ignored.
|
443
|
-
DBus.logger.debug "Unknown message type: #{msg.message_type}"
|
444
|
-
end
|
445
|
-
rescue Exception => e
|
446
|
-
raise msg.annotate_exception(e)
|
447
|
-
end
|
448
|
-
|
449
|
-
# Retrieves the Service with the given _name_.
|
450
|
-
# @return [Service]
|
186
|
+
# Makes a {ProxyService} with the given *name*.
|
187
|
+
# Note that this succeeds even if the name does not exist and cannot be
|
188
|
+
# activated. It will only fail when calling a method.
|
189
|
+
# @return [ProxyService]
|
451
190
|
def service(name)
|
452
191
|
# The service might not exist at this time so we cannot really check
|
453
192
|
# anything
|
@@ -455,27 +194,6 @@ module DBus
|
|
455
194
|
end
|
456
195
|
alias [] service
|
457
196
|
|
458
|
-
# @api private
|
459
|
-
# Emit a signal event for the given _service_, object _obj_, interface
|
460
|
-
# _intf_ and signal _sig_ with arguments _args_.
|
461
|
-
# @param _service unused
|
462
|
-
# @param obj [DBus::Object]
|
463
|
-
# @param intf [Interface]
|
464
|
-
# @param sig [Signal]
|
465
|
-
# @param args arguments for the signal
|
466
|
-
def emit(_service, obj, intf, sig, *args)
|
467
|
-
m = Message.new(DBus::Message::SIGNAL)
|
468
|
-
m.path = obj.path
|
469
|
-
m.interface = intf.name
|
470
|
-
m.member = sig.name
|
471
|
-
i = 0
|
472
|
-
sig.params.each do |par|
|
473
|
-
m.add_param(par.type, args[i])
|
474
|
-
i += 1
|
475
|
-
end
|
476
|
-
@message_queue.push(m)
|
477
|
-
end
|
478
|
-
|
479
197
|
###########################################################################
|
480
198
|
private
|
481
199
|
|
@@ -493,25 +211,6 @@ module DBus
|
|
493
211
|
end
|
494
212
|
end
|
495
213
|
|
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)
|
512
|
-
end
|
513
|
-
end
|
514
|
-
|
515
214
|
# = D-Bus session bus class
|
516
215
|
#
|
517
216
|
# The session bus is a session specific bus (mostly for desktop use).
|
@@ -522,7 +221,6 @@ module DBus
|
|
522
221
|
# Get the the default session bus.
|
523
222
|
def initialize
|
524
223
|
super(self.class.session_bus_address)
|
525
|
-
send_hello
|
526
224
|
end
|
527
225
|
|
528
226
|
def self.session_bus_address
|
@@ -573,7 +271,6 @@ module DBus
|
|
573
271
|
# Get the default system bus.
|
574
272
|
def initialize
|
575
273
|
super(self.class.system_bus_address)
|
576
|
-
send_hello
|
577
274
|
end
|
578
275
|
|
579
276
|
def self.system_bus_address
|
@@ -593,12 +290,8 @@ module DBus
|
|
593
290
|
# you'll need to take care about authentification then, more info here:
|
594
291
|
# https://gitlab.com/pangdudu/ruby-dbus/-/blob/master/README.rdoc
|
595
292
|
# TODO: keep the name but update the docs
|
293
|
+
# @deprecated just use BusConnection
|
596
294
|
class RemoteBus < BusConnection
|
597
|
-
# Get the remote bus.
|
598
|
-
def initialize(socket_name)
|
599
|
-
super(socket_name)
|
600
|
-
send_hello
|
601
|
-
end
|
602
295
|
end
|
603
296
|
|
604
297
|
# See ASystemBus
|
@@ -607,13 +300,13 @@ module DBus
|
|
607
300
|
end
|
608
301
|
|
609
302
|
# Shortcut for the {SystemBus} instance
|
610
|
-
# @return [
|
303
|
+
# @return [BusConnection]
|
611
304
|
def self.system_bus
|
612
305
|
SystemBus.instance
|
613
306
|
end
|
614
307
|
|
615
308
|
# Shortcut for the {SessionBus} instance
|
616
|
-
# @return [
|
309
|
+
# @return [BusConnection]
|
617
310
|
def self.session_bus
|
618
311
|
SessionBus.instance
|
619
312
|
end
|