pangdudu-ruby-dbus 0.2.1 → 0.2.2
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.
- data/lib/dbus/bus.rb +42 -498
- data/lib/dbus/connection.rb +457 -0
- metadata +2 -1
data/lib/dbus/bus.rb
CHANGED
|
@@ -11,11 +11,53 @@
|
|
|
11
11
|
require 'socket'
|
|
12
12
|
require 'thread'
|
|
13
13
|
require 'singleton'
|
|
14
|
+
require 'connection' #outsourced connection module
|
|
14
15
|
|
|
15
16
|
# = D-Bus main module
|
|
16
17
|
#
|
|
17
18
|
# Module containing all the D-Bus modules and classes.
|
|
18
19
|
module DBus
|
|
20
|
+
|
|
21
|
+
# = D-Bus session bus class
|
|
22
|
+
#
|
|
23
|
+
# The session bus is a session specific bus (mostly for desktop use).
|
|
24
|
+
# This is a singleton class.
|
|
25
|
+
class SessionBus < Connection
|
|
26
|
+
include Singleton
|
|
27
|
+
|
|
28
|
+
# Get the the default session bus.
|
|
29
|
+
def initialize
|
|
30
|
+
super(ENV["DBUS_SESSION_BUS_ADDRESS"])
|
|
31
|
+
connect
|
|
32
|
+
send_hello
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# = D-Bus system bus class
|
|
37
|
+
#
|
|
38
|
+
# The system bus is a system-wide bus mostly used for global or
|
|
39
|
+
# system usages. This is a singleton class.
|
|
40
|
+
class SystemBus < Connection
|
|
41
|
+
include Singleton
|
|
42
|
+
|
|
43
|
+
# Get the default system bus.
|
|
44
|
+
def initialize
|
|
45
|
+
super(SystemSocketName)
|
|
46
|
+
connect
|
|
47
|
+
send_hello
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# FIXME: we should get rid of these
|
|
52
|
+
|
|
53
|
+
def DBus.system_bus
|
|
54
|
+
SystemBus.instance
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def DBus.session_bus
|
|
58
|
+
SessionBus.instance
|
|
59
|
+
end
|
|
60
|
+
|
|
19
61
|
# This represents a remote service. It should not be instancied directly
|
|
20
62
|
# Use Bus::service()
|
|
21
63
|
class Service
|
|
@@ -159,504 +201,6 @@ module DBus
|
|
|
159
201
|
end
|
|
160
202
|
end # class Inspect
|
|
161
203
|
|
|
162
|
-
# FIXME: rename Connection to Bus?
|
|
163
|
-
|
|
164
|
-
# D-Bus main connection class
|
|
165
|
-
#
|
|
166
|
-
# Main class that maintains a connection to a bus and can handle incoming
|
|
167
|
-
# and outgoing messages.
|
|
168
|
-
class Connection
|
|
169
|
-
# The unique name (by specification) of the message.
|
|
170
|
-
attr_reader :unique_name
|
|
171
|
-
# The socket that is used to connect with the bus.
|
|
172
|
-
attr_reader :socket
|
|
173
|
-
|
|
174
|
-
# Create a new connection to the bus for a given connect _path_. _path_
|
|
175
|
-
# format is described in the D-Bus specification:
|
|
176
|
-
# http://dbus.freedesktop.org/doc/dbus-specification.html#addresses
|
|
177
|
-
# and is something like:
|
|
178
|
-
# "transport1:key1=value1,key2=value2;transport2:key1=value1,key2=value2"
|
|
179
|
-
# e.g. "unix:path=/tmp/dbus-test"
|
|
180
|
-
#
|
|
181
|
-
# Current implementation of ruby-dbus supports only a single server
|
|
182
|
-
# address and only "unix:path=...,guid=..." and
|
|
183
|
-
# "unix:abstract=...,guid=..." forms
|
|
184
|
-
def initialize(path)
|
|
185
|
-
@path = path
|
|
186
|
-
@unique_name = nil
|
|
187
|
-
@buffer = ""
|
|
188
|
-
@method_call_replies = Hash.new
|
|
189
|
-
@method_call_msgs = Hash.new
|
|
190
|
-
@signal_matchrules = Array.new
|
|
191
|
-
@proxy = nil
|
|
192
|
-
# FIXME: can be TCP or any stream
|
|
193
|
-
@socket = Socket.new(Socket::Constants::PF_UNIX,
|
|
194
|
-
Socket::Constants::SOCK_STREAM, 0)
|
|
195
|
-
@object_root = Node.new("/")
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
# Connect to the bus and initialize the connection.
|
|
199
|
-
def connect
|
|
200
|
-
parse_session_string
|
|
201
|
-
if @transport == "unix" and @type == "abstract"
|
|
202
|
-
if HOST_END == LIL_END
|
|
203
|
-
sockaddr = "\1\0\0#{@unix_abstract}"
|
|
204
|
-
else
|
|
205
|
-
sockaddr = "\0\1\0#{@unix_abstract}"
|
|
206
|
-
end
|
|
207
|
-
elsif @transport == "unix" and @type == "path"
|
|
208
|
-
sockaddr = Socket.pack_sockaddr_un(@unix)
|
|
209
|
-
end
|
|
210
|
-
@socket.connect(sockaddr)
|
|
211
|
-
init_connection
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
# Send the buffer _buf_ to the bus using Connection#writel.
|
|
215
|
-
def send(buf)
|
|
216
|
-
@socket.write(buf)
|
|
217
|
-
end
|
|
218
|
-
|
|
219
|
-
# Tell a bus to register itself on the glib main loop
|
|
220
|
-
def glibize
|
|
221
|
-
require 'glib2'
|
|
222
|
-
# Circumvent a ruby-glib bug
|
|
223
|
-
@channels ||= Array.new
|
|
224
|
-
|
|
225
|
-
gio = GLib::IOChannel.new(@socket.fileno)
|
|
226
|
-
@channels << gio
|
|
227
|
-
gio.add_watch(GLib::IOChannel::IN) do |c, ch|
|
|
228
|
-
update_buffer
|
|
229
|
-
messages.each do |msg|
|
|
230
|
-
process(msg)
|
|
231
|
-
end
|
|
232
|
-
true
|
|
233
|
-
end
|
|
234
|
-
end
|
|
235
|
-
|
|
236
|
-
# FIXME: describe the following names, flags and constants.
|
|
237
|
-
# See DBus spec for definition
|
|
238
|
-
NAME_FLAG_ALLOW_REPLACEMENT = 0x1
|
|
239
|
-
NAME_FLAG_REPLACE_EXISTING = 0x2
|
|
240
|
-
NAME_FLAG_DO_NOT_QUEUE = 0x4
|
|
241
|
-
|
|
242
|
-
REQUEST_NAME_REPLY_PRIMARY_OWNER = 0x1
|
|
243
|
-
REQUEST_NAME_REPLY_IN_QUEUE = 0x2
|
|
244
|
-
REQUEST_NAME_REPLY_EXISTS = 0x3
|
|
245
|
-
REQUEST_NAME_REPLY_ALREADY_OWNER = 0x4
|
|
246
|
-
|
|
247
|
-
DBUSXMLINTRO = '<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
|
|
248
|
-
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
|
249
|
-
<node>
|
|
250
|
-
<interface name="org.freedesktop.DBus.Introspectable">
|
|
251
|
-
<method name="Introspect">
|
|
252
|
-
<arg name="data" direction="out" type="s"/>
|
|
253
|
-
</method>
|
|
254
|
-
</interface>
|
|
255
|
-
<interface name="org.freedesktop.DBus">
|
|
256
|
-
<method name="RequestName">
|
|
257
|
-
<arg direction="in" type="s"/>
|
|
258
|
-
<arg direction="in" type="u"/>
|
|
259
|
-
<arg direction="out" type="u"/>
|
|
260
|
-
</method>
|
|
261
|
-
<method name="ReleaseName">
|
|
262
|
-
<arg direction="in" type="s"/>
|
|
263
|
-
<arg direction="out" type="u"/>
|
|
264
|
-
</method>
|
|
265
|
-
<method name="StartServiceByName">
|
|
266
|
-
<arg direction="in" type="s"/>
|
|
267
|
-
<arg direction="in" type="u"/>
|
|
268
|
-
<arg direction="out" type="u"/>
|
|
269
|
-
</method>
|
|
270
|
-
<method name="Hello">
|
|
271
|
-
<arg direction="out" type="s"/>
|
|
272
|
-
</method>
|
|
273
|
-
<method name="NameHasOwner">
|
|
274
|
-
<arg direction="in" type="s"/>
|
|
275
|
-
<arg direction="out" type="b"/>
|
|
276
|
-
</method>
|
|
277
|
-
<method name="ListNames">
|
|
278
|
-
<arg direction="out" type="as"/>
|
|
279
|
-
</method>
|
|
280
|
-
<method name="ListActivatableNames">
|
|
281
|
-
<arg direction="out" type="as"/>
|
|
282
|
-
</method>
|
|
283
|
-
<method name="AddMatch">
|
|
284
|
-
<arg direction="in" type="s"/>
|
|
285
|
-
</method>
|
|
286
|
-
<method name="RemoveMatch">
|
|
287
|
-
<arg direction="in" type="s"/>
|
|
288
|
-
</method>
|
|
289
|
-
<method name="GetNameOwner">
|
|
290
|
-
<arg direction="in" type="s"/>
|
|
291
|
-
<arg direction="out" type="s"/>
|
|
292
|
-
</method>
|
|
293
|
-
<method name="ListQueuedOwners">
|
|
294
|
-
<arg direction="in" type="s"/>
|
|
295
|
-
<arg direction="out" type="as"/>
|
|
296
|
-
</method>
|
|
297
|
-
<method name="GetConnectionUnixUser">
|
|
298
|
-
<arg direction="in" type="s"/>
|
|
299
|
-
<arg direction="out" type="u"/>
|
|
300
|
-
</method>
|
|
301
|
-
<method name="GetConnectionUnixProcessID">
|
|
302
|
-
<arg direction="in" type="s"/>
|
|
303
|
-
<arg direction="out" type="u"/>
|
|
304
|
-
</method>
|
|
305
|
-
<method name="GetConnectionSELinuxSecurityContext">
|
|
306
|
-
<arg direction="in" type="s"/>
|
|
307
|
-
<arg direction="out" type="ay"/>
|
|
308
|
-
</method>
|
|
309
|
-
<method name="ReloadConfig">
|
|
310
|
-
</method>
|
|
311
|
-
<signal name="NameOwnerChanged">
|
|
312
|
-
<arg type="s"/>
|
|
313
|
-
<arg type="s"/>
|
|
314
|
-
<arg type="s"/>
|
|
315
|
-
</signal>
|
|
316
|
-
<signal name="NameLost">
|
|
317
|
-
<arg type="s"/>
|
|
318
|
-
</signal>
|
|
319
|
-
<signal name="NameAcquired">
|
|
320
|
-
<arg type="s"/>
|
|
321
|
-
</signal>
|
|
322
|
-
</interface>
|
|
323
|
-
</node>
|
|
324
|
-
'
|
|
325
|
-
|
|
326
|
-
def introspect_data(dest, path)
|
|
327
|
-
m = DBus::Message.new(DBus::Message::METHOD_CALL)
|
|
328
|
-
m.path = path
|
|
329
|
-
m.interface = "org.freedesktop.DBus.Introspectable"
|
|
330
|
-
m.destination = dest
|
|
331
|
-
m.member = "Introspect"
|
|
332
|
-
m.sender = unique_name
|
|
333
|
-
if not block_given?
|
|
334
|
-
# introspect in synchronous !
|
|
335
|
-
send_sync(m) do |rmsg|
|
|
336
|
-
if rmsg.is_a?(Error)
|
|
337
|
-
raise rmsg
|
|
338
|
-
else
|
|
339
|
-
return rmsg.params[0]
|
|
340
|
-
end
|
|
341
|
-
end
|
|
342
|
-
else
|
|
343
|
-
send(m.marshall)
|
|
344
|
-
on_return(m) do |rmsg|
|
|
345
|
-
if rmsg.is_a?(Error)
|
|
346
|
-
yield rmsg
|
|
347
|
-
else
|
|
348
|
-
yield rmsg.params[0]
|
|
349
|
-
end
|
|
350
|
-
end
|
|
351
|
-
end
|
|
352
|
-
nil
|
|
353
|
-
end
|
|
354
|
-
|
|
355
|
-
# Issues a call to the org.freedesktop.DBus.Introspectable.Introspect method
|
|
356
|
-
# _dest_ is the service and _path_ the object path you want to introspect
|
|
357
|
-
# If a code block is given, the introspect call in asynchronous. If not
|
|
358
|
-
# data is returned
|
|
359
|
-
#
|
|
360
|
-
# FIXME: link to ProxyObject data definition
|
|
361
|
-
# The returned object is a ProxyObject that has methods you can call to
|
|
362
|
-
# issue somme METHOD_CALL messages, and to setup to receive METHOD_RETURN
|
|
363
|
-
def introspect(dest, path)
|
|
364
|
-
if not block_given?
|
|
365
|
-
# introspect in synchronous !
|
|
366
|
-
data = introspect_data(dest, path)
|
|
367
|
-
pof = DBus::ProxyObjectFactory.new(data, self, dest, path)
|
|
368
|
-
return pof.build
|
|
369
|
-
else
|
|
370
|
-
introspect_data(dest, path) do |data|
|
|
371
|
-
yield(DBus::ProxyObjectFactory.new(data, self, dest, path).build)
|
|
372
|
-
end
|
|
373
|
-
end
|
|
374
|
-
end
|
|
375
|
-
|
|
376
|
-
# Exception raised when a service name is requested that is not available.
|
|
377
|
-
class NameRequestError < Exception
|
|
378
|
-
end
|
|
379
|
-
|
|
380
|
-
# Attempt to request a service _name_.
|
|
381
|
-
def request_service(name)
|
|
382
|
-
r = proxy.RequestName(name, NAME_FLAG_REPLACE_EXISTING)
|
|
383
|
-
raise NameRequestError if r[0] != REQUEST_NAME_REPLY_PRIMARY_OWNER
|
|
384
|
-
@service = Service.new(name, self)
|
|
385
|
-
@service
|
|
386
|
-
end
|
|
387
|
-
|
|
388
|
-
# Set up a ProxyObject for the bus itself, since the bus is introspectable.
|
|
389
|
-
# Returns the object.
|
|
390
|
-
def proxy
|
|
391
|
-
if @proxy == nil
|
|
392
|
-
path = "/org/freedesktop/DBus"
|
|
393
|
-
dest = "org.freedesktop.DBus"
|
|
394
|
-
pof = DBus::ProxyObjectFactory.new(DBUSXMLINTRO, self, dest, path)
|
|
395
|
-
@proxy = pof.build["org.freedesktop.DBus"]
|
|
396
|
-
end
|
|
397
|
-
@proxy
|
|
398
|
-
end
|
|
399
|
-
|
|
400
|
-
# Fill (append) the buffer from data that might be available on the
|
|
401
|
-
# socket.
|
|
402
|
-
def update_buffer
|
|
403
|
-
@buffer += @socket.read_nonblock(MSG_BUF_SIZE)
|
|
404
|
-
end
|
|
405
|
-
|
|
406
|
-
# Get one message from the bus and remove it from the buffer.
|
|
407
|
-
# Return the message.
|
|
408
|
-
def pop_message
|
|
409
|
-
ret = nil
|
|
410
|
-
begin
|
|
411
|
-
ret, size = Message.new.unmarshall_buffer(@buffer)
|
|
412
|
-
@buffer.slice!(0, size)
|
|
413
|
-
rescue IncompleteBufferException => e
|
|
414
|
-
# fall through, let ret be null
|
|
415
|
-
end
|
|
416
|
-
ret
|
|
417
|
-
end
|
|
418
|
-
|
|
419
|
-
# Retrieve all the messages that are currently in the buffer.
|
|
420
|
-
def messages
|
|
421
|
-
ret = Array.new
|
|
422
|
-
while msg = pop_message
|
|
423
|
-
ret << msg
|
|
424
|
-
end
|
|
425
|
-
ret
|
|
426
|
-
end
|
|
427
|
-
|
|
428
|
-
# The buffer size for messages.
|
|
429
|
-
MSG_BUF_SIZE = 4096
|
|
430
|
-
|
|
431
|
-
# Update the buffer and retrieve all messages using Connection#messages.
|
|
432
|
-
# Return the messages.
|
|
433
|
-
def poll_messages
|
|
434
|
-
ret = nil
|
|
435
|
-
r, d, d = IO.select([@socket], nil, nil, 0)
|
|
436
|
-
if r and r.size > 0
|
|
437
|
-
update_buffer
|
|
438
|
-
end
|
|
439
|
-
messages
|
|
440
|
-
end
|
|
441
|
-
|
|
442
|
-
# Wait for a message to arrive. Return it once it is available.
|
|
443
|
-
def wait_for_message
|
|
444
|
-
ret = pop_message
|
|
445
|
-
while ret == nil
|
|
446
|
-
r, d, d = IO.select([@socket])
|
|
447
|
-
if r and r[0] == @socket
|
|
448
|
-
update_buffer
|
|
449
|
-
ret = pop_message
|
|
450
|
-
end
|
|
451
|
-
end
|
|
452
|
-
ret
|
|
453
|
-
end
|
|
454
|
-
|
|
455
|
-
# Send a message _m_ on to the bus. This is done synchronously, thus
|
|
456
|
-
# the call will block until a reply message arrives.
|
|
457
|
-
def send_sync(m, &retc) # :yields: reply/return message
|
|
458
|
-
send(m.marshall)
|
|
459
|
-
@method_call_msgs[m.serial] = m
|
|
460
|
-
@method_call_replies[m.serial] = retc
|
|
461
|
-
|
|
462
|
-
retm = wait_for_message
|
|
463
|
-
process(retm)
|
|
464
|
-
until [DBus::Message::ERROR,
|
|
465
|
-
DBus::Message::METHOD_RETURN].include?(retm.message_type) and
|
|
466
|
-
retm.reply_serial == m.serial
|
|
467
|
-
retm = wait_for_message
|
|
468
|
-
process(retm)
|
|
469
|
-
end
|
|
470
|
-
end
|
|
471
|
-
|
|
472
|
-
# Specify a code block that has to be executed when a reply for
|
|
473
|
-
# message _m_ is received.
|
|
474
|
-
def on_return(m, &retc)
|
|
475
|
-
# Have a better exception here
|
|
476
|
-
if m.message_type != Message::METHOD_CALL
|
|
477
|
-
raise "on_return should only get method_calls"
|
|
478
|
-
end
|
|
479
|
-
@method_call_msgs[m.serial] = m
|
|
480
|
-
@method_call_replies[m.serial] = retc
|
|
481
|
-
end
|
|
482
|
-
|
|
483
|
-
# Asks bus to send us messages matching mr, and execute slot when
|
|
484
|
-
# received
|
|
485
|
-
def add_match(mr, &slot)
|
|
486
|
-
# check this is a signal.
|
|
487
|
-
@signal_matchrules << [mr, slot]
|
|
488
|
-
self.proxy.AddMatch(mr.to_s)
|
|
489
|
-
end
|
|
490
|
-
|
|
491
|
-
# Process a message _m_ based on its type.
|
|
492
|
-
# method call:: FIXME...
|
|
493
|
-
# method call return value:: FIXME...
|
|
494
|
-
# signal:: FIXME...
|
|
495
|
-
# error:: FIXME...
|
|
496
|
-
def process(m)
|
|
497
|
-
case m.message_type
|
|
498
|
-
when Message::ERROR, Message::METHOD_RETURN
|
|
499
|
-
raise InvalidPacketException if m.reply_serial == nil
|
|
500
|
-
mcs = @method_call_replies[m.reply_serial]
|
|
501
|
-
if not mcs
|
|
502
|
-
puts "no return code for #{mcs.inspect} (#{m.inspect})" if $DEBUG
|
|
503
|
-
else
|
|
504
|
-
if m.message_type == Message::ERROR
|
|
505
|
-
mcs.call(Error.new(m))
|
|
506
|
-
else
|
|
507
|
-
mcs.call(m)
|
|
508
|
-
end
|
|
509
|
-
@method_call_replies.delete(m.reply_serial)
|
|
510
|
-
@method_call_msgs.delete(m.reply_serial)
|
|
511
|
-
end
|
|
512
|
-
when DBus::Message::METHOD_CALL
|
|
513
|
-
if m.path == "/org/freedesktop/DBus"
|
|
514
|
-
puts "Got method call on /org/freedesktop/DBus" if $DEBUG
|
|
515
|
-
end
|
|
516
|
-
# handle introspectable as an exception:
|
|
517
|
-
if m.interface == "org.freedesktop.DBus.Introspectable" and
|
|
518
|
-
m.member == "Introspect"
|
|
519
|
-
reply = Message.new(Message::METHOD_RETURN).reply_to(m)
|
|
520
|
-
reply.sender = @unique_name
|
|
521
|
-
node = @service.get_node(m.path)
|
|
522
|
-
raise NotImplementedError if not node
|
|
523
|
-
reply.sender = @unique_name
|
|
524
|
-
reply.add_param(Type::STRING, @service.get_node(m.path).to_xml)
|
|
525
|
-
send(reply.marshall)
|
|
526
|
-
else
|
|
527
|
-
node = @service.get_node(m.path)
|
|
528
|
-
return if node.nil?
|
|
529
|
-
obj = node.object
|
|
530
|
-
return if obj.nil?
|
|
531
|
-
obj.dispatch(m) if obj
|
|
532
|
-
end
|
|
533
|
-
when DBus::Message::SIGNAL
|
|
534
|
-
@signal_matchrules.each do |elem|
|
|
535
|
-
mr, slot = elem
|
|
536
|
-
if mr.match(m)
|
|
537
|
-
slot.call(m)
|
|
538
|
-
return
|
|
539
|
-
end
|
|
540
|
-
end
|
|
541
|
-
else
|
|
542
|
-
puts "Unknown message type: #{m.message_type}" if $DEBUG
|
|
543
|
-
end
|
|
544
|
-
end
|
|
545
|
-
|
|
546
|
-
# Retrieves the service with the given _name_.
|
|
547
|
-
def service(name)
|
|
548
|
-
# The service might not exist at this time so we cannot really check
|
|
549
|
-
# anything
|
|
550
|
-
Service.new(name, self)
|
|
551
|
-
end
|
|
552
|
-
alias :[] :service
|
|
553
|
-
|
|
554
|
-
# Emit a signal event for the given _service_, object _obj_, interface
|
|
555
|
-
# _intf_ and signal _sig_ with arguments _args_.
|
|
556
|
-
def emit(service, obj, intf, sig, *args)
|
|
557
|
-
m = Message.new(DBus::Message::SIGNAL)
|
|
558
|
-
m.path = obj.path
|
|
559
|
-
m.interface = intf.name
|
|
560
|
-
m.member = sig.name
|
|
561
|
-
m.sender = service.name
|
|
562
|
-
i = 0
|
|
563
|
-
sig.params.each do |par|
|
|
564
|
-
m.add_param(par[1], args[i])
|
|
565
|
-
i += 1
|
|
566
|
-
end
|
|
567
|
-
send(m.marshall)
|
|
568
|
-
end
|
|
569
|
-
|
|
570
|
-
###########################################################################
|
|
571
|
-
private
|
|
572
|
-
|
|
573
|
-
# Send a hello messages to the bus to let it know we are here.
|
|
574
|
-
def send_hello
|
|
575
|
-
m = Message.new(DBus::Message::METHOD_CALL)
|
|
576
|
-
m.path = "/org/freedesktop/DBus"
|
|
577
|
-
m.destination = "org.freedesktop.DBus"
|
|
578
|
-
m.interface = "org.freedesktop.DBus"
|
|
579
|
-
m.member = "Hello"
|
|
580
|
-
send_sync(m) do |rmsg|
|
|
581
|
-
@unique_name = rmsg.destination
|
|
582
|
-
puts "Got hello reply. Our unique_name is #{@unique_name}" if $DEBUG
|
|
583
|
-
end
|
|
584
|
-
end
|
|
585
|
-
|
|
586
|
-
# Parse the session string (socket address).
|
|
587
|
-
def parse_session_string
|
|
588
|
-
path_parsed = /^([^:]*):([^;]*)$/.match(@path)
|
|
589
|
-
@transport = path_parsed[1]
|
|
590
|
-
adr = path_parsed[2]
|
|
591
|
-
if @transport == "unix"
|
|
592
|
-
adr.split(",").each do |eqstr|
|
|
593
|
-
idx, val = eqstr.split("=")
|
|
594
|
-
case idx
|
|
595
|
-
when "path"
|
|
596
|
-
@type = idx
|
|
597
|
-
@unix = val
|
|
598
|
-
when "abstract"
|
|
599
|
-
@type = idx
|
|
600
|
-
@unix_abstract = val
|
|
601
|
-
when "guid"
|
|
602
|
-
@guid = val
|
|
603
|
-
end
|
|
604
|
-
end
|
|
605
|
-
end
|
|
606
|
-
end
|
|
607
|
-
|
|
608
|
-
# Initialize the connection to the bus.
|
|
609
|
-
def init_connection
|
|
610
|
-
@client = Client.new(@socket)
|
|
611
|
-
@client.authenticate
|
|
612
|
-
# TODO: code some real stuff here
|
|
613
|
-
#writel("AUTH EXTERNAL 31303030")
|
|
614
|
-
#s = readl
|
|
615
|
-
# parse OK ?
|
|
616
|
-
#writel("BEGIN")
|
|
617
|
-
end
|
|
618
|
-
end # class Connection
|
|
619
|
-
|
|
620
|
-
# = D-Bus session bus class
|
|
621
|
-
#
|
|
622
|
-
# The session bus is a session specific bus (mostly for desktop use).
|
|
623
|
-
# This is a singleton class.
|
|
624
|
-
class SessionBus < Connection
|
|
625
|
-
include Singleton
|
|
626
|
-
|
|
627
|
-
# Get the the default session bus.
|
|
628
|
-
def initialize
|
|
629
|
-
super(ENV["DBUS_SESSION_BUS_ADDRESS"])
|
|
630
|
-
connect
|
|
631
|
-
send_hello
|
|
632
|
-
end
|
|
633
|
-
end
|
|
634
|
-
|
|
635
|
-
# = D-Bus system bus class
|
|
636
|
-
#
|
|
637
|
-
# The system bus is a system-wide bus mostly used for global or
|
|
638
|
-
# system usages. This is a singleton class.
|
|
639
|
-
class SystemBus < Connection
|
|
640
|
-
include Singleton
|
|
641
|
-
|
|
642
|
-
# Get the default system bus.
|
|
643
|
-
def initialize
|
|
644
|
-
super(SystemSocketName)
|
|
645
|
-
connect
|
|
646
|
-
send_hello
|
|
647
|
-
end
|
|
648
|
-
end
|
|
649
|
-
|
|
650
|
-
# FIXME: we should get rid of these
|
|
651
|
-
|
|
652
|
-
def DBus.system_bus
|
|
653
|
-
SystemBus.instance
|
|
654
|
-
end
|
|
655
|
-
|
|
656
|
-
def DBus.session_bus
|
|
657
|
-
SessionBus.instance
|
|
658
|
-
end
|
|
659
|
-
|
|
660
204
|
# = Main event loop class.
|
|
661
205
|
#
|
|
662
206
|
# Class that takes care of handling message and signal events
|
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
# D-Bus main connection class
|
|
2
|
+
#
|
|
3
|
+
# Main class that maintains a connection to a bus and can handle incoming
|
|
4
|
+
# and outgoing messages.
|
|
5
|
+
class Connection
|
|
6
|
+
# The unique name (by specification) of the message.
|
|
7
|
+
attr_reader :unique_name
|
|
8
|
+
# The socket that is used to connect with the bus.
|
|
9
|
+
attr_reader :socket
|
|
10
|
+
|
|
11
|
+
# Create a new connection to the bus for a given connect _path_. _path_
|
|
12
|
+
# format is described in the D-Bus specification:
|
|
13
|
+
# http://dbus.freedesktop.org/doc/dbus-specification.html#addresses
|
|
14
|
+
# and is something like:
|
|
15
|
+
# "transport1:key1=value1,key2=value2;transport2:key1=value1,key2=value2"
|
|
16
|
+
# e.g. "unix:path=/tmp/dbus-test"
|
|
17
|
+
#
|
|
18
|
+
# Current implementation of ruby-dbus supports only a single server
|
|
19
|
+
# address and only "unix:path=...,guid=..." and
|
|
20
|
+
# "unix:abstract=...,guid=..." forms
|
|
21
|
+
def initialize(path)
|
|
22
|
+
@path = path
|
|
23
|
+
@unique_name = nil
|
|
24
|
+
@buffer = ""
|
|
25
|
+
@method_call_replies = Hash.new
|
|
26
|
+
@method_call_msgs = Hash.new
|
|
27
|
+
@signal_matchrules = Array.new
|
|
28
|
+
@proxy = nil
|
|
29
|
+
# FIXME: can be TCP or any stream
|
|
30
|
+
@socket = Socket.new(Socket::Constants::PF_UNIX,
|
|
31
|
+
Socket::Constants::SOCK_STREAM, 0)
|
|
32
|
+
@object_root = Node.new("/")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Connect to the bus and initialize the connection.
|
|
36
|
+
def connect
|
|
37
|
+
parse_session_string
|
|
38
|
+
if @transport == "unix" and @type == "abstract"
|
|
39
|
+
if HOST_END == LIL_END
|
|
40
|
+
sockaddr = "\1\0\0#{@unix_abstract}"
|
|
41
|
+
else
|
|
42
|
+
sockaddr = "\0\1\0#{@unix_abstract}"
|
|
43
|
+
end
|
|
44
|
+
elsif @transport == "unix" and @type == "path"
|
|
45
|
+
sockaddr = Socket.pack_sockaddr_un(@unix)
|
|
46
|
+
end
|
|
47
|
+
@socket.connect(sockaddr)
|
|
48
|
+
init_connection
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Send the buffer _buf_ to the bus using Connection#writel.
|
|
52
|
+
def send(buf)
|
|
53
|
+
@socket.write(buf)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Tell a bus to register itself on the glib main loop
|
|
57
|
+
def glibize
|
|
58
|
+
puts "dbus/bus.rb-221: Entered glibize."
|
|
59
|
+
require 'glib2'
|
|
60
|
+
# Circumvent a ruby-glib bug
|
|
61
|
+
@channels ||= Array.new
|
|
62
|
+
|
|
63
|
+
gio = GLib::IOChannel.new(@socket.fileno)
|
|
64
|
+
@channels << gio
|
|
65
|
+
gio.add_watch(GLib::IOChannel::IN) do |c, ch|
|
|
66
|
+
update_buffer
|
|
67
|
+
messages.each do |msg|
|
|
68
|
+
process(msg)
|
|
69
|
+
end
|
|
70
|
+
true
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# FIXME: describe the following names, flags and constants.
|
|
75
|
+
# See DBus spec for definition
|
|
76
|
+
NAME_FLAG_ALLOW_REPLACEMENT = 0x1
|
|
77
|
+
NAME_FLAG_REPLACE_EXISTING = 0x2
|
|
78
|
+
NAME_FLAG_DO_NOT_QUEUE = 0x4
|
|
79
|
+
|
|
80
|
+
REQUEST_NAME_REPLY_PRIMARY_OWNER = 0x1
|
|
81
|
+
REQUEST_NAME_REPLY_IN_QUEUE = 0x2
|
|
82
|
+
REQUEST_NAME_REPLY_EXISTS = 0x3
|
|
83
|
+
REQUEST_NAME_REPLY_ALREADY_OWNER = 0x4
|
|
84
|
+
|
|
85
|
+
DBUSXMLINTRO = '<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
|
|
86
|
+
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
|
87
|
+
<node>
|
|
88
|
+
<interface name="org.freedesktop.DBus.Introspectable">
|
|
89
|
+
<method name="Introspect">
|
|
90
|
+
<arg name="data" direction="out" type="s"/>
|
|
91
|
+
</method>
|
|
92
|
+
</interface>
|
|
93
|
+
<interface name="org.freedesktop.DBus">
|
|
94
|
+
<method name="RequestName">
|
|
95
|
+
<arg direction="in" type="s"/>
|
|
96
|
+
<arg direction="in" type="u"/>
|
|
97
|
+
<arg direction="out" type="u"/>
|
|
98
|
+
</method>
|
|
99
|
+
<method name="ReleaseName">
|
|
100
|
+
<arg direction="in" type="s"/>
|
|
101
|
+
<arg direction="out" type="u"/>
|
|
102
|
+
</method>
|
|
103
|
+
<method name="StartServiceByName">
|
|
104
|
+
<arg direction="in" type="s"/>
|
|
105
|
+
<arg direction="in" type="u"/>
|
|
106
|
+
<arg direction="out" type="u"/>
|
|
107
|
+
</method>
|
|
108
|
+
<method name="Hello">
|
|
109
|
+
<arg direction="out" type="s"/>
|
|
110
|
+
</method>
|
|
111
|
+
<method name="NameHasOwner">
|
|
112
|
+
<arg direction="in" type="s"/>
|
|
113
|
+
<arg direction="out" type="b"/>
|
|
114
|
+
</method>
|
|
115
|
+
<method name="ListNames">
|
|
116
|
+
<arg direction="out" type="as"/>
|
|
117
|
+
</method>
|
|
118
|
+
<method name="ListActivatableNames">
|
|
119
|
+
<arg direction="out" type="as"/>
|
|
120
|
+
</method>
|
|
121
|
+
<method name="AddMatch">
|
|
122
|
+
<arg direction="in" type="s"/>
|
|
123
|
+
</method>
|
|
124
|
+
<method name="RemoveMatch">
|
|
125
|
+
<arg direction="in" type="s"/>
|
|
126
|
+
</method>
|
|
127
|
+
<method name="GetNameOwner">
|
|
128
|
+
<arg direction="in" type="s"/>
|
|
129
|
+
<arg direction="out" type="s"/>
|
|
130
|
+
</method>
|
|
131
|
+
<method name="ListQueuedOwners">
|
|
132
|
+
<arg direction="in" type="s"/>
|
|
133
|
+
<arg direction="out" type="as"/>
|
|
134
|
+
</method>
|
|
135
|
+
<method name="GetConnectionUnixUser">
|
|
136
|
+
<arg direction="in" type="s"/>
|
|
137
|
+
<arg direction="out" type="u"/>
|
|
138
|
+
</method>
|
|
139
|
+
<method name="GetConnectionUnixProcessID">
|
|
140
|
+
<arg direction="in" type="s"/>
|
|
141
|
+
<arg direction="out" type="u"/>
|
|
142
|
+
</method>
|
|
143
|
+
<method name="GetConnectionSELinuxSecurityContext">
|
|
144
|
+
<arg direction="in" type="s"/>
|
|
145
|
+
<arg direction="out" type="ay"/>
|
|
146
|
+
</method>
|
|
147
|
+
<method name="ReloadConfig">
|
|
148
|
+
</method>
|
|
149
|
+
<signal name="NameOwnerChanged">
|
|
150
|
+
<arg type="s"/>
|
|
151
|
+
<arg type="s"/>
|
|
152
|
+
<arg type="s"/>
|
|
153
|
+
</signal>
|
|
154
|
+
<signal name="NameLost">
|
|
155
|
+
<arg type="s"/>
|
|
156
|
+
</signal>
|
|
157
|
+
<signal name="NameAcquired">
|
|
158
|
+
<arg type="s"/>
|
|
159
|
+
</signal>
|
|
160
|
+
</interface>
|
|
161
|
+
</node>
|
|
162
|
+
'
|
|
163
|
+
|
|
164
|
+
def introspect_data(dest, path)
|
|
165
|
+
m = DBus::Message.new(DBus::Message::METHOD_CALL)
|
|
166
|
+
m.path = path
|
|
167
|
+
m.interface = "org.freedesktop.DBus.Introspectable"
|
|
168
|
+
m.destination = dest
|
|
169
|
+
m.member = "Introspect"
|
|
170
|
+
m.sender = unique_name
|
|
171
|
+
if not block_given?
|
|
172
|
+
# introspect in synchronous !
|
|
173
|
+
send_sync(m) do |rmsg|
|
|
174
|
+
if rmsg.is_a?(Error)
|
|
175
|
+
raise rmsg
|
|
176
|
+
else
|
|
177
|
+
return rmsg.params[0]
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
else
|
|
181
|
+
send(m.marshall)
|
|
182
|
+
on_return(m) do |rmsg|
|
|
183
|
+
if rmsg.is_a?(Error)
|
|
184
|
+
yield rmsg
|
|
185
|
+
else
|
|
186
|
+
yield rmsg.params[0]
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
nil
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Issues a call to the org.freedesktop.DBus.Introspectable.Introspect method
|
|
194
|
+
# _dest_ is the service and _path_ the object path you want to introspect
|
|
195
|
+
# If a code block is given, the introspect call in asynchronous. If not
|
|
196
|
+
# data is returned
|
|
197
|
+
#
|
|
198
|
+
# FIXME: link to ProxyObject data definition
|
|
199
|
+
# The returned object is a ProxyObject that has methods you can call to
|
|
200
|
+
# issue somme METHOD_CALL messages, and to setup to receive METHOD_RETURN
|
|
201
|
+
def introspect(dest, path)
|
|
202
|
+
if not block_given?
|
|
203
|
+
# introspect in synchronous !
|
|
204
|
+
data = introspect_data(dest, path)
|
|
205
|
+
pof = DBus::ProxyObjectFactory.new(data, self, dest, path)
|
|
206
|
+
return pof.build
|
|
207
|
+
else
|
|
208
|
+
introspect_data(dest, path) do |data|
|
|
209
|
+
yield(DBus::ProxyObjectFactory.new(data, self, dest, path).build)
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# Exception raised when a service name is requested that is not available.
|
|
215
|
+
class NameRequestError < Exception
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
# Attempt to request a service _name_.
|
|
219
|
+
def request_service(name)
|
|
220
|
+
r = proxy.RequestName(name, NAME_FLAG_REPLACE_EXISTING)
|
|
221
|
+
raise NameRequestError if r[0] != REQUEST_NAME_REPLY_PRIMARY_OWNER
|
|
222
|
+
@service = Service.new(name, self)
|
|
223
|
+
@service
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# Set up a ProxyObject for the bus itself, since the bus is introspectable.
|
|
227
|
+
# Returns the object.
|
|
228
|
+
def proxy
|
|
229
|
+
if @proxy == nil
|
|
230
|
+
path = "/org/freedesktop/DBus"
|
|
231
|
+
dest = "org.freedesktop.DBus"
|
|
232
|
+
pof = DBus::ProxyObjectFactory.new(DBUSXMLINTRO, self, dest, path)
|
|
233
|
+
@proxy = pof.build["org.freedesktop.DBus"]
|
|
234
|
+
end
|
|
235
|
+
@proxy
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
# Fill (append) the buffer from data that might be available on the
|
|
239
|
+
# socket.
|
|
240
|
+
def update_buffer
|
|
241
|
+
@buffer += @socket.read_nonblock(MSG_BUF_SIZE)
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
# Get one message from the bus and remove it from the buffer.
|
|
245
|
+
# Return the message.
|
|
246
|
+
def pop_message
|
|
247
|
+
ret = nil
|
|
248
|
+
begin
|
|
249
|
+
ret, size = Message.new.unmarshall_buffer(@buffer)
|
|
250
|
+
@buffer.slice!(0, size)
|
|
251
|
+
rescue IncompleteBufferException => e
|
|
252
|
+
# fall through, let ret be null
|
|
253
|
+
end
|
|
254
|
+
ret
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
# Retrieve all the messages that are currently in the buffer.
|
|
258
|
+
def messages
|
|
259
|
+
ret = Array.new
|
|
260
|
+
while msg = pop_message
|
|
261
|
+
ret << msg
|
|
262
|
+
end
|
|
263
|
+
ret
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
# The buffer size for messages.
|
|
267
|
+
MSG_BUF_SIZE = 4096
|
|
268
|
+
|
|
269
|
+
# Update the buffer and retrieve all messages using Connection#messages.
|
|
270
|
+
# Return the messages.
|
|
271
|
+
def poll_messages
|
|
272
|
+
ret = nil
|
|
273
|
+
r, d, d = IO.select([@socket], nil, nil, 0)
|
|
274
|
+
if r and r.size > 0
|
|
275
|
+
update_buffer
|
|
276
|
+
end
|
|
277
|
+
messages
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
# Wait for a message to arrive. Return it once it is available.
|
|
281
|
+
def wait_for_message
|
|
282
|
+
ret = pop_message
|
|
283
|
+
while ret == nil
|
|
284
|
+
r, d, d = IO.select([@socket])
|
|
285
|
+
if r and r[0] == @socket
|
|
286
|
+
update_buffer
|
|
287
|
+
ret = pop_message
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
ret
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
# Send a message _m_ on to the bus. This is done synchronously, thus
|
|
294
|
+
# the call will block until a reply message arrives.
|
|
295
|
+
def send_sync(m, &retc) # :yields: reply/return message
|
|
296
|
+
send(m.marshall)
|
|
297
|
+
@method_call_msgs[m.serial] = m
|
|
298
|
+
@method_call_replies[m.serial] = retc
|
|
299
|
+
|
|
300
|
+
retm = wait_for_message
|
|
301
|
+
process(retm)
|
|
302
|
+
until [DBus::Message::ERROR,
|
|
303
|
+
DBus::Message::METHOD_RETURN].include?(retm.message_type) and
|
|
304
|
+
retm.reply_serial == m.serial
|
|
305
|
+
retm = wait_for_message
|
|
306
|
+
process(retm)
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
# Specify a code block that has to be executed when a reply for
|
|
311
|
+
# message _m_ is received.
|
|
312
|
+
def on_return(m, &retc)
|
|
313
|
+
# Have a better exception here
|
|
314
|
+
if m.message_type != Message::METHOD_CALL
|
|
315
|
+
raise "on_return should only get method_calls"
|
|
316
|
+
end
|
|
317
|
+
@method_call_msgs[m.serial] = m
|
|
318
|
+
@method_call_replies[m.serial] = retc
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
# Asks bus to send us messages matching mr, and execute slot when
|
|
322
|
+
# received
|
|
323
|
+
def add_match(mr, &slot)
|
|
324
|
+
# check this is a signal.
|
|
325
|
+
@signal_matchrules << [mr, slot]
|
|
326
|
+
self.proxy.AddMatch(mr.to_s)
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
# Process a message _m_ based on its type.
|
|
330
|
+
# method call:: FIXME...
|
|
331
|
+
# method call return value:: FIXME...
|
|
332
|
+
# signal:: FIXME...
|
|
333
|
+
# error:: FIXME...
|
|
334
|
+
def process(m)
|
|
335
|
+
case m.message_type
|
|
336
|
+
when Message::ERROR, Message::METHOD_RETURN
|
|
337
|
+
raise InvalidPacketException if m.reply_serial == nil
|
|
338
|
+
mcs = @method_call_replies[m.reply_serial]
|
|
339
|
+
if not mcs
|
|
340
|
+
puts "no return code for #{mcs.inspect} (#{m.inspect})" if $DEBUG
|
|
341
|
+
else
|
|
342
|
+
if m.message_type == Message::ERROR
|
|
343
|
+
mcs.call(Error.new(m))
|
|
344
|
+
else
|
|
345
|
+
mcs.call(m)
|
|
346
|
+
end
|
|
347
|
+
@method_call_replies.delete(m.reply_serial)
|
|
348
|
+
@method_call_msgs.delete(m.reply_serial)
|
|
349
|
+
end
|
|
350
|
+
when DBus::Message::METHOD_CALL
|
|
351
|
+
if m.path == "/org/freedesktop/DBus"
|
|
352
|
+
puts "Got method call on /org/freedesktop/DBus" if $DEBUG
|
|
353
|
+
end
|
|
354
|
+
# handle introspectable as an exception:
|
|
355
|
+
if m.interface == "org.freedesktop.DBus.Introspectable" and
|
|
356
|
+
m.member == "Introspect"
|
|
357
|
+
reply = Message.new(Message::METHOD_RETURN).reply_to(m)
|
|
358
|
+
reply.sender = @unique_name
|
|
359
|
+
node = @service.get_node(m.path)
|
|
360
|
+
raise NotImplementedError if not node
|
|
361
|
+
reply.sender = @unique_name
|
|
362
|
+
reply.add_param(Type::STRING, @service.get_node(m.path).to_xml)
|
|
363
|
+
send(reply.marshall)
|
|
364
|
+
else
|
|
365
|
+
node = @service.get_node(m.path)
|
|
366
|
+
return if node.nil?
|
|
367
|
+
obj = node.object
|
|
368
|
+
return if obj.nil?
|
|
369
|
+
obj.dispatch(m) if obj
|
|
370
|
+
end
|
|
371
|
+
when DBus::Message::SIGNAL
|
|
372
|
+
@signal_matchrules.each do |elem|
|
|
373
|
+
mr, slot = elem
|
|
374
|
+
if mr.match(m)
|
|
375
|
+
slot.call(m)
|
|
376
|
+
return
|
|
377
|
+
end
|
|
378
|
+
end
|
|
379
|
+
else
|
|
380
|
+
puts "Unknown message type: #{m.message_type}" if $DEBUG
|
|
381
|
+
end
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
# Retrieves the service with the given _name_.
|
|
385
|
+
def service(name)
|
|
386
|
+
# The service might not exist at this time so we cannot really check
|
|
387
|
+
# anything
|
|
388
|
+
Service.new(name, self)
|
|
389
|
+
end
|
|
390
|
+
alias :[] :service
|
|
391
|
+
|
|
392
|
+
# Emit a signal event for the given _service_, object _obj_, interface
|
|
393
|
+
# _intf_ and signal _sig_ with arguments _args_.
|
|
394
|
+
def emit(service, obj, intf, sig, *args)
|
|
395
|
+
m = Message.new(DBus::Message::SIGNAL)
|
|
396
|
+
m.path = obj.path
|
|
397
|
+
m.interface = intf.name
|
|
398
|
+
m.member = sig.name
|
|
399
|
+
m.sender = service.name
|
|
400
|
+
i = 0
|
|
401
|
+
sig.params.each do |par|
|
|
402
|
+
m.add_param(par[1], args[i])
|
|
403
|
+
i += 1
|
|
404
|
+
end
|
|
405
|
+
send(m.marshall)
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
###########################################################################
|
|
409
|
+
private
|
|
410
|
+
|
|
411
|
+
# Send a hello messages to the bus to let it know we are here.
|
|
412
|
+
def send_hello
|
|
413
|
+
m = Message.new(DBus::Message::METHOD_CALL)
|
|
414
|
+
m.path = "/org/freedesktop/DBus"
|
|
415
|
+
m.destination = "org.freedesktop.DBus"
|
|
416
|
+
m.interface = "org.freedesktop.DBus"
|
|
417
|
+
m.member = "Hello"
|
|
418
|
+
send_sync(m) do |rmsg|
|
|
419
|
+
@unique_name = rmsg.destination
|
|
420
|
+
puts "Got hello reply. Our unique_name is #{@unique_name}" if $DEBUG
|
|
421
|
+
end
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
# Parse the session string (socket address).
|
|
425
|
+
def parse_session_string
|
|
426
|
+
path_parsed = /^([^:]*):([^;]*)$/.match(@path)
|
|
427
|
+
@transport = path_parsed[1]
|
|
428
|
+
adr = path_parsed[2]
|
|
429
|
+
if @transport == "unix"
|
|
430
|
+
adr.split(",").each do |eqstr|
|
|
431
|
+
idx, val = eqstr.split("=")
|
|
432
|
+
case idx
|
|
433
|
+
when "path"
|
|
434
|
+
@type = idx
|
|
435
|
+
@unix = val
|
|
436
|
+
when "abstract"
|
|
437
|
+
@type = idx
|
|
438
|
+
@unix_abstract = val
|
|
439
|
+
when "guid"
|
|
440
|
+
@guid = val
|
|
441
|
+
end
|
|
442
|
+
end
|
|
443
|
+
end
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
# Initialize the connection to the bus.
|
|
447
|
+
def init_connection
|
|
448
|
+
@client = Client.new(@socket)
|
|
449
|
+
@client.authenticate
|
|
450
|
+
# TODO: code some real stuff here
|
|
451
|
+
#writel("AUTH EXTERNAL 31303030")
|
|
452
|
+
#s = readl
|
|
453
|
+
# parse OK ?
|
|
454
|
+
#writel("BEGIN")
|
|
455
|
+
end
|
|
456
|
+
end # class Connection
|
|
457
|
+
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pangdudu-ruby-dbus
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ruby DBUS Team
|
|
@@ -51,6 +51,7 @@ files:
|
|
|
51
51
|
- lib/dbus/introspect.rb
|
|
52
52
|
- lib/dbus/matchrule.rb
|
|
53
53
|
- lib/dbus/bus.rb
|
|
54
|
+
- lib/dbus/connection.rb
|
|
54
55
|
- lib/dbus.rb
|
|
55
56
|
- ChangeLog
|
|
56
57
|
- COPYING
|