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:
- 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.
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:
- ctrl table The ProxyController instance.
- timeout number The timeout (in milliseconds) to use for subsequent proxy requests. Two special values are allowed as well: TIMEOUT_USE_DEFAULT and TIMEOUT_INFINITE. The default value (if none is specified) is TIMEOUT_USE_DEFAULT.
- 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:
- 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.
- 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.
- 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:
- bool Returns true if the message is sent successfully or false if there was an error.
- 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:
- userdata or nil The reply message of type METHOD_RETURN or nil if a D-Bus error message was returned or another error detected.
- 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.
- 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.