Module l2dbus.proxyctrl

Proxy Controller Module.

This module provides an abstract controller/proxy client class library for communicating with a remote D-Bus service. Based on either the D-Bus XML introspection data for a service or an explicit description in Lua, the class provides a mechanism to dynamically generate a true proxy interface for the methods and properties exposed by the remote D-Bus service.

See the description of the getProxy method for a better understanding on how to use the proxied interfaces to call methods or get/set properties of an interface.

Functions

new (conn, busName, objPath) Constructs a new ProxyController instance.

ProxyController

bind (ctrl) Binds the controller to the remote service using D-Bus introspection.
bindNoIntrospect (ctrl, introspectionData) Binds the controller to the remote service without D-Bus introspection.
unbind (ctrl) Unbinds the controller from the remote service.
getIntrospectionData (ctrl) Retrieves the introspection data from the ProxyController.
getProxy (ctrl, interface) Retrieves the actual proxy for the remote D-Bus service.
setTimeout (ctrl, timeout) Sets the timeout to use for all proxy requests.
getTimeout (ctrl) Gets the timeout used for all proxy requests.
setBlockingMode (ctrl, mode) Sets the blocking mode used by the ProxyController to make calls.
getBlockingMode (ctrl) Gets the blocking mode used by the ProxyController to make calls.
setProxyNoReplyNeeded (ctrl, mode) Sets whether proxy method calls expect/need a reply from the far-end.
getProxyNoReplyNeeded (ctrl) Indicates whether proxy calls need/expect a reply from the far-end.
connectSignal (ctrl, interface, sigName, handler) Connects a handler to an interface's signal.
disconnectSignal (ctrl, hnd) Disconnects the specified handler from the D-Bus signal.
disconnectAllSignals (ctrl) Disconnects all the signal handlers from the ProxyController.
sendMessage (ctrl, msg) Sends a D-Bus message depending on the blocking mode of the ProxyController.
sendMessageNoReply (ctrl, msg) Sends a D-Bus message indicating it does not expect a reply.
waitForReply (ctrl, pendingCall) Waits for a reply from a pending call.
parseXml (ctrl, xmlStr) Parses D-Bus introspection XML data a returns a Lua table equivalent.


Functions

new (conn, busName, objPath)
Constructs a new ProxyController instance.

The constructor creates a ProxyController instance. As its name implies the object controls the behavior and configuration of a proxy. These configurable items include things like the timeout used by the proxy, blocking mode, and the actual dynamic generation of the proxy itself based on metadata gleaned from the remote object (via D-Bus introspection or provided directly). The ProxyController exposes the actual remote service proxy including methods and properties via separate objects that eliminate namespace collisions between the controller's methods and those of the remote service.

Parameters:

  • conn userdata The Connection to attach the controller to.
  • busName string The D-Bus bus name on which the remote service is offered.
  • objPath string The remote service's object path.

Returns:

    table A proxy controller instance.

ProxyController

bind (ctrl)
Binds the controller to the remote service using D-Bus introspection.

This method will attempt to introspect the remote service associated with this ProxyController. This implies that the Connection associated with the controller must be connected and the remote service must support introspection. The method may throw a Lua error if an exceptional (unexpected) error occurs.

Parameters:

  • ctrl table The ProxyController instance.

Returns:

  1. true or nil Returns true if the binding operation succeeds or nil on failure.
  2. string or nil Returns an error name or nil if a name is unavailable and the binding operation fails.
  3. string or nil Returns an error message or nil if a message is unavailable and the binding operation fails.
bindNoIntrospect (ctrl, introspectionData)
Binds the controller to the remote service without D-Bus introspection.

This method uses the provided introspection data (either formatted as D-Bus introspection XML or a Lua introspection table) to bind with the remote service. This method makes no attempt to contact the remote service for this data by sending messages on the bus. If the data is provided as D-Bus introspection XML then it will internally be parsed and converted into a Lua introspection table. The structure of a Lua introspection table takes the following form:

    {
        ["interface_name_1"] = {

            interface = "interface_name_1",

            properties = {
                prop_name_1 = {
                    sig = "i",
                    access = "r"
                },
                prop_name_2 = {
                    sig = "s",
                    access = "rw"
                },
                ...
                prop_name_N = {
                    sig = "u",
                    access = "w"
                },
            },

            signals = {
                sig_name_1 = {
                    {
                        sig = "s",
                        dir = "out"
                    }
                },
                sig_name_2 = {
                    {
                        sig = "i",
                        dir = "out"
                    },
                    {
                        sig = "as",
                        dir = "out"
                    }
                },
                ...
                sig_name_N = {
                    {
                        sig = "t",
                        dir = "out"
                    },
                    {
                        sig = "i",
                        dir = "out"
                    }
                }
            },

            methods = {
                method_name_1 = {
                    {
                        sig = "as",
                        dir = "out"
                    }
                },

                method_name_2 = {
                    {
                        sig = "s",
                        dir = "in"
                    },
                    {
                        sig = "i",
                        dir = "out"
                    }
                },
                ...
                method_name_N = {
                    {
                        sig = "u",
                        dir = "in"
                    }
                }
            },
        },
        ...
        ["interface_name_N"] = {
            ...
        }

Introspection data that is not formatted as D-Bus XML introspection data must adhere to the structure of the Lua introspection table above. This table is comprised of one or more interface tables. Each interface table has a properties, signals, and methods table. It also has a (seemingly) redundant entry for the interface name which helps speed up interface lookups. The method, signal, and property tables themselves can have multiple entries with individual methods and signals having zero or more arguments. When fed an XML formatted D-Bus interface description a similar table is generated and stored internally.

WARNING: Validation is not done on a Lua introspectionData table passed into this function. It is assumed to be structured correctly. Minimal validation is done if this introspection data is passed in as XML.

Parameters:

  • ctrl table The ProxyController instance.
  • introspectionData string or table The introspection data either expressed as the D-Bus XML introspection string or a Lua introspection table as above.

Returns:

    true Returns true if the binding operation succeeds. If the introspection data cannot be parsed then a Lua error may be thrown.
unbind (ctrl)
Unbinds the controller from the remote service.

This method unbinds or disconnects the ProxyController from the remote service by effectively erasing any previous introspection data. The call the bind or bindNoIntrospect must be executed again in order to interact with the remote D-Bus service.

Parameters:

  • ctrl table The ProxyController instance.
getIntrospectionData (ctrl)
Retrieves the introspection data from the ProxyController.

This method returns the D-Bus introspection data as a Lua table described in the documentation for bindNoIntrospect. This can be useful to understand how D-Bus XML introspection data is converted to a Lua table representation.

Parameters:

  • ctrl table The ProxyController instance.
getProxy (ctrl, interface)
Retrieves the actual proxy for the remote D-Bus service.

This method returns a proxy for the named interface. The actual proxy has two sub-objects named p and m. These sub-objects split the interface namespace into properties (p) and methods (m) avoiding the possibility of name collisions. Before you can get the proxy the ProxyController must be bound to a remote service. An example of how to access methods or properties on a remote service is shown below:

    -- Example of making a BLOCKING call on a proxy
    local proxyCtrl, proxy, status, pending, reply, enabled
    proxyCtrl = proxy.new(conn, "org.freedesktop.NetworkManager",
                        /org/freedesktop/NetworkManager")
    -- Bind to the remote service
    proxyCtrl:bind()
    -- Put the controller in blocking mode
    proxyCtrl:setBlockingMode(true)
    -- Get the actual proxy for the interface we're interested in
    proxy = proxyCtrl:getProxy("org.freedesktop.NetworkManager")
    status, names = proxy.m.GetDevices()
    if status then
        print("We got device names")
    end
    -- Use the "getter" sub-object to read the value of a property
    status, enabled = proxy.p.get.WirelessEnabled()
    if status then
        -- Set the property but indicate we're not interested
        -- in the response ('true' == no response needed)
        proxy.p.set.WirelessEnabled(not enabled, true)
    end


    -- Example of making a NON-BLOCKING call on a proxy
    local proxyCtrl, proxy, status, pending, reply, enabled
    proxyCtrl = proxy.new(conn, "org.freedesktop.NetworkManager",
                        "/org/freedesktop/NetworkManager")
    proxyCtrl:bind()
    -- The proxy calls to the remote service are non-blocking now
    proxyCtrl:setBlockingMode(false)
    -- Get the proxy for the interface we're interested in
    proxy = proxyCtrl:getProxy("org.freedesktop.NetworkManager")
    -- If everything goes smoothly (status == true) the 'pending' is
    -- a PendingCall object.
    status, pending = proxy.m.GetDevices()
    if status then
        -- Wait to get a reply. Will yield if called from a coroutine
        -- other than the "main" one.
        status, reply = proxyCtrl:waitForReply(pending)
        if status then
            print("We got device names")
        end
    end
    -- Properties are retrieved in the same way as before
    status, pending = proxy.p.get.WirelessEnabled()
    if status then
        -- Wait for the property "get" request to complete
        status, enabled = proxyCtrl:waitForReply(pending)
        if status then
            print("We got the Wireless state")
            -- Again, set the property but indicate (true) that no
            -- reply is needed.
            proxy.p.set.WirelessEnabled(enabled, true)
        end
    end

The method and property sub-objects expose the remote methods and properties of a bound service interface. The property sub-object (p) is further split into properties that are writable (e.g. can be set) and those that can only be read (e.g. get). So the p sub-object of a proxy has two sub-objects called set and get. Beneath these sub-objects are the names of all the properties for that interface split across these two set/get boundaries. For properties that are read/write the identical name may appear under both set and get.

Methods or properties that are called will typically return two (or more) parameters at a minimum.

  • status (bool) True if the call completed without error, false otherwise.
  • arg1..argN|PendingCall|errName (any|userdata|string) If status is true and proxy calls are configured to expect a reply, if the ProxyController is configured to be blocking, the remote service return values (arg1..argN) are returned. A non-blocking call expecting a reply will result in a PendingCall being returned. If no reply is expected then this argument will be the D-Bus serial number of the request message. If the status is false then generally a D-Bus error name is returned.
  • errMsg (string|nil) If status were false then the third parameter would be an optional error message or nil if one is not available.


Method and property calls can also result in a Lua error being thrown. Generally these are reserved for truly exceptional conditions or programming errors (e.g. wrong parameters, types, etc...). D-Bus error messages returned by a remote service do not generate Lua errors but rather the error name and message are returned with status set to false. In general the calls on the proxy do not need to be made with a Lua protected call (pcall) unless every possible exception needs to be caught.

Parameters:

  • ctrl table The ProxyController instance.
  • interface string The D-Bus interface name for which to retrieve the proxy. This interface must be an element of the introspection data. A Lua error is generated if the interface is not supported.

Returns:

    table The actual proxy for the remote service.
setTimeout (ctrl, timeout)
Sets the timeout to use for all proxy requests.

This method sets the timeout used by all subsequent proxied calls on the remote service. The timeout is specified in milliseconds. It is not possible to set the timeout individually for each proxy method/property call unless this method is called prior to the method/property invocation.

Parameters:

getTimeout (ctrl)
Gets the timeout used for all proxy requests.

This method gets the timeout used by all proxied calls on the remote service. The timeout is specified in milliseconds but may have two special values: TIMEOUT_USE_DEFAULT and TIMEOUT_INFINITE.

Parameters:

  • ctrl table The ProxyController instance.

Returns:

    number The proxy-wide timeout value in milliseconds.
setBlockingMode (ctrl, mode)
Sets the blocking mode used by the ProxyController to make calls.

This method sets the blocking mode (true == blocking, false == non-blocking) used by proxied calls to a remote service. Blocking calls will in fact block the thread of Lua execution. Non-blocking calls will return a PendingCall object which the caller can use to either block waiting for an answer or be notified later that a reply has arrived.

Parameters:

  • ctrl table The ProxyController instance.
  • mode bool Set to true for blocking mode, false for non-blocking mode.
getBlockingMode (ctrl)
Gets the blocking mode used by the ProxyController to make calls.

This method returns the blocking mode of the ProxyController. If it returns true then it will make blocking proxy calls. If it returns false then it's configured to make non-blocking calls.

Parameters:

  • ctrl table The ProxyController instance.

Returns:

    bool The blocking mode where true == blocking, false == non-blocking.
setProxyNoReplyNeeded (ctrl, mode)
Sets whether proxy method calls expect/need a reply from the far-end.

This method determines whether proxy calls to the far-end need a response. Specifically, if set to true, out-going messages are marked to indicate that a reply is not needed so that the far-end can decide whether or not to reply to the message. The far-end can always reply regardless of the flag but it means the near-end will ignore the reply. The default setting for the controller is false which means replies are expected from the far-end. If set to true out-going messages are marked to indicate a reply is not needed by using the call to sendMessageNoReply to transmit the request message rather than sendMessage. This setting applies to all subsequent proxy method calls made after the value is changed. The behavior of individual proxy method calls can only be controlled by calling this method before making the method call on the proxy.

Parameters:

  • ctrl table The ProxyController instance.
  • mode bool Set to true if no reply is needed/expected, false to indicate a reply is expected.
getProxyNoReplyNeeded (ctrl)
Indicates whether proxy calls need/expect a reply from the far-end.

This method returns an indication of whether proxy method calls expect a reply from the far-end. If this returns true then no reply is needed and proxy method calls will not wait to hear the reply to a request. If false is returned (the default behavior) then it is expected that proxy method calls will return a reply message.

Parameters:

  • ctrl table The ProxyController instance.

Returns:

    bool Returns true if no reply is expected from the far-end, false (the default) if every proxy request expects a reply.
connectSignal (ctrl, interface, sigName, handler)
Connects a handler to an interface's signal.

This method registers a D-Bus Match handler for a signal on a specific interface.

Parameters:

  • ctrl table The ProxyController instance.
  • interface string A valid D-Bus interface name. This interface must be defined in the introspection data for this ProxyController.
  • sigName string The name of the D-Bus signal to connect the handler.
  • handler func The handler that is called when the signal is received. The signature of this handler is as follows:

        function onSignal(arg1, arg2, ..., argN)
            ...
        end
    

    Where the arguments (argN) are defined the same as specified in the D-Bus introspection XML description for the signal.

Returns:

    lightuserdata An opaque handle to the connection that can be used later to disconnect the handler.
disconnectSignal (ctrl, hnd)
Disconnects the specified handler from the D-Bus signal.

Given the opaque handle returned by connectSignal this method can be used to disconnect the handler from that signal.

Parameters:

  • ctrl table The ProxyController instance.
  • hnd lightuserdata The opaque handle returned by connectSignal

Returns:

    bool Returns true if disconnected successfully, false otherwise.
disconnectAllSignals (ctrl)
Disconnects all the signal handlers from the ProxyController.

The method disconnects all the signal handlers that have been connected to all the interfaces. If a signal fails to be disconnected a Lua error may be thrown indicating the disconnect failed.

Parameters:

  • ctrl table The ProxyController instance.
sendMessage (ctrl, msg)
Sends a D-Bus message depending on the blocking mode of the ProxyController.

This method sends a D-Bus message depending on the blocking mode of the ProxyController. If the blocking mode is set to blocking then the call will wait on a reply (or timeout) and if everything is successful a D-Bus message of type METHOD_RETURN is returned. Non-blocking calls (on success) will return a PendingCsendMessageNoReplyall object that the caller can use to wait on or be notified of the reply. Proxy calls, internally use this method to execute calls to remote services.

Parameters:

  • ctrl table The ProxyController instance.
  • msg userdata The D-Bus message to send.

Returns:

  1. userdata or nil If the controller is configuring in a non-blocking mode then return a PendingCall object if the message is sent successfully otherwise return nil. If the controller is configured in a blocking mode then either return the reply D-Bus message (type = METHOD_RETURN) or nil if a D-Bus error message is returned or another error is detected.
  2. string or nil If the first return argument is nil then return the D-Bus error name associated with the error. If there was no error or an error name was not provided then return nil.
  3. string or nil If the first return argument is nil then return an optional error message associated with the error. If there was no error or a message was not provided then return nil.
sendMessageNoReply (ctrl, msg)
Sends a D-Bus message indicating it does not expect a reply.

This method provides an optimization for the called service indicating the client is not waiting for a reply. The called service may either choose not to send a reply, or if it does, the reply will be ignored and discarded by the client. It's intent is to reduce the amount of round-trip messaging to a minimum.

Parameters:

  • ctrl table The ProxyController instance.
  • msg userdata The D-Bus message to send.

Returns:

  1. bool Returns true if the message is sent successfully or false if there was an error.
  2. number or nil Returns the D-Bus serial number of the message if sent successfully or nil if it could not be sent.
waitForReply (ctrl, pendingCall)
Waits for a reply from a pending call.

This method is called with a PendingCall object and uses it to wait for a reply from a remote service. How it waits is largely dependent on whether or not this method was called from the "main" Lua coroutine or a different one. Since the "main" Lua coroutine cannot yield this call will translate into a purely blocking call that will block the Lua VM. If it is not the main Lua coroutine (or thread) then the coroutine will yield waiting for a reply. When the reply or a timeout occurs the thread will be resumed and the reply message returned. If this method is called from a secondary coroutine then it MUST NOT be called via a Lua pcall (or protected call) since this waitForReply may yield and under Lua 5.1 yielding across a protected call is not allowed.

Parameters:

  • ctrl table The ProxyController instance.
  • pendingCall userdata The PendingCall object.

Returns:

  1. userdata or nil The reply message of type METHOD_RETURN or nil if a D-Bus error message was returned or another error detected.
  2. string or nil If the first return argument is nil then return the D-Bus error name associated with the error. If there was no error or an error name was not provided then return nil.
  3. string or nil If the first return argument is nil then return an optional error message associated with the error. If there was no error or a message was not provided then return nil.
parseXml (ctrl, xmlStr)
Parses D-Bus introspection XML data a returns a Lua table equivalent.

This method parses D-Bus introspection data and converts it to an internal Lua table representation which is used to generate the necessary proxy objects. The XML parser used to parse this data is not a full-blown, fully validating parser and has known limitations. See the l2dbus.xml module for more details.

Parameters:

  • ctrl table The ProxyController instance.
  • xmlStr string A string containing valid D-Bus instrospection XML describing the interfaces exposed by a service object.

Returns:

    table Returns a Lua table representation of the parsed XML introspection. See bindNoIntrospect for a description of the layout of this table.
generated by LDoc 1.3