Class: DBus::BusConnection

Inherits:
Connection show all
Defined in:
lib/dbus/bus.rb

Overview

A regular Bus Connection. As opposed to a peer connection to a single counterparty with no daemon in between.

Direct Known Subclasses

ASessionBus, ASystemBus, RemoteBus

Constant Summary collapse

RELEASE_NAME_REPLY_RELEASED =

The caller has released his claim on the given name. Either the caller was the primary owner of the name, and the name is now unused

or taken by somebody waiting in the queue for the name,

or the caller was waiting in the queue for the name and has now been removed from the queue.

1
RELEASE_NAME_REPLY_NON_EXISTENT =

The given name does not exist on this bus.

2
RELEASE_NAME_REPLY_NOT_OWNER =

The caller was not the primary owner of this name, and was also not waiting in the queue to own this name.

3

Constants inherited from Connection

Connection::NAME_FLAG_ALLOW_REPLACEMENT, Connection::NAME_FLAG_DO_NOT_QUEUE, Connection::NAME_FLAG_REPLACE_EXISTING, Connection::REQUEST_NAME_REPLY_ALREADY_OWNER, Connection::REQUEST_NAME_REPLY_EXISTS, Connection::REQUEST_NAME_REPLY_IN_QUEUE, Connection::REQUEST_NAME_REPLY_PRIMARY_OWNER

Instance Attribute Summary collapse

Attributes inherited from Connection

#message_queue

Instance Method Summary collapse

Methods inherited from Connection

#dispatch_message_queue, #emit, #glibize, #handle_return_of_request_name, #introspect, #introspect_data, #object_server, #on_return, #process, #request_service, #send_sync, #send_sync_or_async, #wait_for_message

Constructor Details

#initialize(addresses) ⇒ BusConnection

Connect, authenticate, and send Hello.



31
32
33
34
35
36
# File 'lib/dbus/bus.rb', line 31

def initialize(addresses)
  super
  @unique_name = nil
  @proxy = nil
  send_hello
end

Instance Attribute Details

#unique_nameObject (readonly)

The unique name (by specification) of the message.



26
27
28
# File 'lib/dbus/bus.rb', line 26

def unique_name
  @unique_name
end

Instance Method Details

#add_match(match_rule, &slot) ⇒ void

This method returns an undefined value.

Asks bus to send us messages matching mr, and execute slot when received

Parameters:



163
164
165
166
167
168
169
170
171
# File 'lib/dbus/bus.rb', line 163

def add_match(match_rule, &slot)
  mrs = match_rule.to_s
  rule_existed = super(mrs, &slot)
  # don't ask for the same match if we override it
  return if rule_existed

  DBus.logger.debug "Asked for a new match"
  proxy.AddMatch(mrs)
end

#on_name_acquired(&handler) ⇒ Object



151
152
153
# File 'lib/dbus/bus.rb', line 151

def on_name_acquired(&handler)
  proxy.on_signal("NameAcquired", &handler)
end

#on_name_lost(&handler) ⇒ Object



155
156
157
# File 'lib/dbus/bus.rb', line 155

def on_name_lost(&handler)
  proxy.on_signal("NameLost", &handler)
end

#proxyProxyObject

Set up a ProxyObject for the bus itself, since the bus is introspectable. Returns the object.

Returns:



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/dbus/bus.rb', line 42

def proxy
  if @proxy.nil?
    xml_filename = File.expand_path("org.freedesktop.DBus.xml", __dir__)
    xml = File.read(xml_filename)

    path = "/org/freedesktop/DBus"
    dest = "org.freedesktop.DBus"
    pof = DBus::ProxyObjectFactory.new(
      xml, self, dest, path,
      api: ApiOptions::A0
    )
    @proxy = pof.build["org.freedesktop.DBus"]
  end
  @proxy
end

#release_name(name) ⇒ Object

Parameters:

  • name (BusName)

    the name to release



146
147
148
149
# File 'lib/dbus/bus.rb', line 146

def release_name(name)
  name = BusName.new(name)
  proxy.ReleaseName(name).first
end

#remove_match(match_rule) ⇒ void

This method returns an undefined value.

Parameters:



175
176
177
178
179
180
181
182
183
184
# File 'lib/dbus/bus.rb', line 175

def remove_match(match_rule)
  mrs = match_rule.to_s
  rule_existed = super(mrs)
  # don't remove nonexisting matches.
  return if rule_existed

  # FIXME: if we do try, the Error.MatchRuleNotFound is *not* raised
  # and instead is reported as "no return code for nil"
  proxy.RemoveMatch(mrs)
end

#request_name(name, allow_replacement: false, replace_existing: false, queue: false, flags: nil) ⇒ REQUEST_NAME_REPLY_PRIMARY_OWNER, REQUEST_NAME_REPLY_ALREADY_OWNER

Note:

Parameters other than name are advanced, you probably don’t need them.

Request a well-known name so that clients can find us. With no boolean flags, running a second instance of a program that calls ‘request_name` will result in the second one failing, which this library translates to an exception. If you want the second instance to take over, you need both `allow_replacement: true` and `replace_existing: true.`

Examples:

Simple usage

bus = DBus.session_bus
bus.object_server.export(DBus::Object.new("/org/example/Test"))
bus.request_name("org.example.Test")
# main loop

Second instance taking over

bus = DBus.session_bus
bus.object_server.export(DBus::Object.new("/org/example/Test"))
bus.on_name_lost { exit }
bus.request_name("org.example.Test", allow_replacement: true, replace_existing: true)
# main loop

Second instance waiting for its turn

bus = DBus.session_bus
bus.object_server.export(DBus::Object.new("/org/example/Test"))
bus.on_name_acquired { @owner = true }
begin
  bus.request_name("org.example.Test", queue: true)
rescue DBus::Connection::NameRequestError => e
  @owner = false
end
# main loop

Parameters:

  • name (BusName)

    the requested name

  • replace_existing (Boolean) (defaults to: false)

    Replace an existing owner of the name, if that owner set allow_replacement.

  • allow_replacement (Boolean) (defaults to: false)

    Other connections that specify replace_existing will be able to take the name from us. We will get NameLost. If we specified queue we may get the name again, with NameAcquired.

  • queue (Boolean) (defaults to: false)

    Affects the behavior when the bus denies the name (sooner or later).

    • If ‘false` (default), it is recommended to let the `NameRequestError` fall through and end your program.

    • If ‘true`, you should `rescue` the `NameRequestError` and set up NameAcquired and NameLost handlers. Meanwhile, the bus will put us in a queue waiting for name (this is the “sooner” case). Also, if we had `allow_replacement: true`, another connection can cause us to lose the name. We will be moved back to the queue, waiting for when the other owners give up (the “later” case).

  • flags (Integer, nil) (defaults to: nil)

    If specified, overrides the boolean parameters. Use a bitwise sum ‘|` of:

    • NAME_FLAG_ALLOW_REPLACEMENT

    • NAME_FLAG_REPLACE_EXISTING

    • NAME_FLAG_DO_NOT_QUEUE

    Note that ‘0` implies `queue: true`.

Returns:

Raises:

  • (NameRequestError)

    with #error_code REQUEST_NAME_REPLY_EXISTS or REQUEST_NAME_REPLY_IN_QUEUE, on failure

  • DBus::Error another way to fail is being prohibited to own the name which is the default on the system bus

See Also:



120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/dbus/bus.rb', line 120

def request_name(name,
                 allow_replacement: false,
                 replace_existing: false,
                 queue: false,
                 flags: nil)
  if flags.nil?
    flags = (allow_replacement ? NAME_FLAG_ALLOW_REPLACEMENT : 0) |
            (replace_existing ? NAME_FLAG_REPLACE_EXISTING : 0) |
            (queue ? 0 : NAME_FLAG_DO_NOT_QUEUE)
  end
  name = BusName.new(name)
  r = proxy.RequestName(name, flags).first
  handle_return_of_request_name(r, name)
end

#service(name) ⇒ ProxyService Also known as: []

Makes a ProxyService with the given name. Note that this succeeds even if the name does not exist and cannot be activated. It will only fail when calling a method.

Returns:



190
191
192
193
194
# File 'lib/dbus/bus.rb', line 190

def service(name)
  # The service might not exist at this time so we cannot really check
  # anything
  ProxyService.new(name, self)
end