/* qdbusconnection.h TQT_DBusConnection object * * Copyright (C) 2005 Harald Fernengel * Copyright (C) 2005-2007 Kevin Krammer * * Licensed under the Academic Free License version 2.1 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. * */ #ifndef TQDBUSCONNECTION_H #define TQDBUSCONNECTION_H /** * @mainpage TQt3 Bindings for D-Bus * * D-Bus is an IPC (inter process communication) technology designed to allow * applications to interoperate without requiring tight coupling. * * For more information about D-Bus itself see its website: * http://www.freedesktop.org/wiki/Software_2fdbus * * The TQt3 D-Bus bindings described here are a TQt3 style API around the base * implementation to enable TQt3 developers to use D-Bus in their applications * without requiring them to know about the details of the C based D-Bus API. * * The two main use cases are: * - using the API to access service implemented in other applications. * See section @ref dbusclient for an introduction on this * * - using the API to provide access to services implemented in your application * See section @ref dbusservice for an introduction on this * * Of course an application can do both at the same time. */ /** * @page dbusconventions Naming and syntax conventions in D-Bus * * @section dbusconventions-servicename Service names * * The service name is D-Bus application identifier, i.e. either * the unique name handed out to the peer application by the bus on connect * (see TQT_DBusConnection::uniqueName()) or, more likely, a well known name the * peer application has requested, see TQT_DBusConnection::requestName() * * Such well known names have the form of word separated by dots, like * Internet domain names but in reverse order. * * For example the name for the bus itself (the D-Bus daemon) would be * @code * "org.freedesktop.DBus" * @endcode * * @section dbusconventions-objectpath Object paths * * The object path is like an address within the peer host application. * The path format looks like a Unix file path, i.e. words separated by * slash @c '/' characters. * * For example the path for the bus itself (the D-Bus daemon's main object) * would be * @code * "/org/freedesktop/DBus" * @endcode * * @section dbusconventions-interfacename Interface names * * The interface name specifies which group of methods and signals * implemented by the peer service object is used in proxy operations. * * Interface names have the form of word separated by dots, like Internet * domain names but in reverse order or like a fully qualified Java class name. * * For example the interface for the bus itself (the D-Bus daemon's main * interface) would be * @code * "org.freedesktop.DBus" * @endcode * * @section dbusconventions-errorname Error names * * A D-Bus error name is a sequence of words separated by dots, similar * to D-Bus service names or interface names, or like a fully qualified * Java class name. * * For example if a D-Bus service does not handle a method invocation sent * to it because it doesn't know about the method it will return a D-Bus * error named * @code * "org.freedesktop.DBus.Error.UnknownMethod" * @endcode * TQT_DBusError can create some of the more common errors based on a type value * and decode their names into the type respectively. See TQT_DBusError#ErrorType * * @section dbusconventions-membername Method and signal names * * There is no mandatory convention for member names, neither for methods nor * for signals. * * However, using the standard interfaces of D-Bus as a hint, it is recommended * to use "camel case" names starting with an uppercase letter, for example * @code * "GetConnectionUnixUser" * @endcode */ #include "tqdbusmacros.h" #include class TQT_DBusConnectionPrivate; class TQT_DBusError; class TQT_DBusMessage; class TQT_DBusObjectBase; class TQObject; /** * @brief Provides access to a specific D-Bus bus * * In order to access a D-Bus message bus an application has to connect to it. * This is very similar to connecting to an FTP server using TQFtp, where any * number of commands can be sent in sequence over the same connection. * * Additionally to the asynchronous command execution provided by TQFtp a * TQT_DBusConnection can also execute synchronous (blocking) calls so the * code around those calls stays closer to in-process method incovations. * * However it is recommended to only perform blocking calls on D-Bus service * methods that are likely to be processed fast. * * TQT_DBusConnection implements a shared resource, i.e. if you create a * connection with a specific name in one part of your code and then * create one with the same name somewhere else, the second creation will * actually return the same shared connection object the first caller created. * * The application can be connected to more than one message bus simultaniously * using one or more connections per bus, however the most common case is to * have one connection per bus. * * The two main bus types are: * - System bus: a bus connecting applications on one system across user * or session boundaries, for example allowing to communicate * with system services like printer spoolers, etc * * - Session bus: a bus connecting applications within one user session, for * example started at login or by a session manager. Use cases * or this kind of bus would be accessing user specific * resources like addressbooks, retrieving user settings or * controlling session services (e.g. disabling screensaver * in a video player application during playback) * * While TQT_DBusConnection provides the basic API to access D-Bus services * it is more convenient to use TQT_DBusProxy on top of the connection. * * See sections @ref dbusclient and @ref dbusservice for examples */ class TQDBUS_EXPORT TQT_DBusConnection { public: /** * DBus bus types */ enum BusType { /** * The session bus is a user and user session specific message * channel. It will usually be started by a login script or a * session manager. */ SessionBus, /** * The system bus is a message channel bridging user level and * system level process boundaries, e.g. it can allow a user process * with normal user access restrictions to perform a limited subset * of operations on a process running with elevated rights. * * @warning if an applications exposed services on the system bus, i.e. * registers objects using registerObject(), it should be * carefully examined on potential security issues */ SystemBus, // TODO find out about ActivationBus purpose ActivationBus }; /** * @brief Creates an empty/disconnected connection handle * * This is mainly used for initializing variables of this type, i.e. like * the default TQString constructor. * * A variable set to such an empty connection can be assigned a working * connection at any time. */ TQT_DBusConnection(); /** * @brief Creates a connection handle to a named connection * * This will result in an disconnected connection handle if no * connection with that name has been created by addConnection before. * * Therefore it is recommended to use addConnection() instead to get a * connection handle. * * @param name identifier of the shared connection object */ TQT_DBusConnection(const TQString &name); /** * @brief Creates a shallow copy of the given connection * * Allows to pass connection handles around by value, similar to TQString * thus avoiding problems like dangling pointers in application code * * @param other the connection to copy from */ TQT_DBusConnection(const TQT_DBusConnection &other); /** * @brief Destroys the connection handle * * If this handle is the last one referencing the shared connection object * it will delete it, disconnecting it from any objects it was * collaborating with */ ~TQT_DBusConnection(); /** * @brief Creates a shallow copy of the given connection * * Allows to pass connection handles around by value, similar to TQString * thus avoiding problems like dangling pointers in application code * * @param other the connection to copy from * * @return a reference to this instance as required by assigment operator * semantics */ TQT_DBusConnection &operator=(const TQT_DBusConnection &other); /** * @brief Returns whether the connection is connected to a bus * * @return @c true if the connection can be used, @c false if the handle * does not have access to a shared connection object or if the * connection to the bus could not be established or broke */ bool isConnected() const; /** * @brief Returns the last error seen by the connection * * This can be a connection error, e.g. attempt to connect failed, or a * transmission error or an error reported by a method call * * @return the last error seen by the connection */ TQT_DBusError lastError() const; /** * @brief Flags for controlling the behavior name collision handling * * @see requestName() */ enum NameRequestMode { /** * Do not allow others to take over a name requested by this * application */ NoReplace = 0, /** * Allow other applications that request the same name to get it, * i.e. allow the bus to transfer the name from this application * to the one requesting it */ AllowReplace = 1, /** * Try to get the name transferred from the current owner to this * application. This will only work if the other application as * requested the name using the AllowReplace flag */ ReplaceExisting = 2 }; /** * @brief Requests to be addressable on the bus by a given name * * Each connection to a bus gets a unique name once the connection is * established. This is similar to getting an IP address when connecting * to the Internet. * * If an application's purpose is to provide services to other applications * the other applications require to know how to address the service * provider. Similar to a domain name on the Internet D-Bus allows to * register names on the bus and be addressed through those names instead * of the connection identifier. * * @note this is not required if the application only needs to acccess * services or only implements generic service APIs * * If more than one application request the same name, D-Bus will try * to resolve this conflict as good as possible. * The #NameRequestMode flags allow to control how an application prefers * to be treated in such a conflict. * * @param name the name the connection should be addressable with. See * section @ref dbusconventions-servicename * @param modeFlags an OR'ed combination of #NameRequestMode flags * * @return @c true if the name request was successfull, @c false if * the connection is not connected to a bus or the name is already * taken and cannot be tranferred * * @see uniqueName() */ bool requestName(const TQString &name, int modeFlags = NoReplace); /** * @brief Returns the connection identifier assigned at connect * * The unique name is the connection address or identifier the bus assigned * to this connection when it got established. * * @return the connection's unique bus identifier * * @see requestName() */ TQString uniqueName() const; /** * @brief Sends a message over the bus * * Sends a message composed through the TQT_DBusMessage API to the bus. * This is the main method for service objects (see TQT_DBusObjectBase) to * send replies and errors for method calls they accepted or for sending * D-Bus signals. * * @note for doing method calls it is more convenient to use TQT_DBusProxy, * see TQT_DBusProxy::send() * * @param message the message to send * * @return @c true if sending succeeded, @c false if the connection is not * connected, if the message lacks information about the recepient * or if sending fails a at a lower level in the communication * stack * * @see lastError() */ bool send(const TQT_DBusMessage &message) const; /** * @brief Sends a message over the bus and waits for the reply * * Sends a message composed through the TQT_DBusMessage API to the bus. * It then blocks and waits until the associated reply is received. * Any message received in between is stored and can be processed * by calling dispatch() or scheduleDispatch() * * @note for doing method calls it is more convenient to use TQT_DBusProxy, * see TQT_DBusProxy::sendWithReply() * * @param message the message to send * @param error an optional parameter to directly get any error that might * occur during processing of the call * * @return a message containing either the call's reply or an invalid * message in case the call failed * * @see lastError() */ TQT_DBusMessage sendWithReply(const TQT_DBusMessage &message, TQT_DBusError *error = 0) const; /** * @brief Sends a message over the bus, specifying a receiver object for * replies * * Sends a message composed through the TQT_DBusMessage API to the bus and * returns an identifier number to associate with the reply once it is * received by the given receiver. * See TQT_DBusMessage::replySerialNumber() * * The required slot signature is * @code * void slotname(const TQT_DBusMessage&); * @endcode * * @note for doing method calls it is more convenient to use TQT_DBusProxy, * see TQT_DBusProxy::sendWithAsyncReply() * * @param message the message to send * @param receiver the TQObject to relay the reply to * @param slot the slot to invoke for the reply * * @return a numeric identifier for association with the reply or @c 0 if * sending failed * * @see lastError() */ int sendWithAsyncReply(const TQT_DBusMessage &message, TQObject *receiver, const char *slot) const; /** * @brief Flushes buffered outgoing message * * Attempts to send all enqueued outgoing messages before returning. */ void flush() const; /** * @brief Processes buffered inbound messages * * Attempts to process all enqueued inbound messages, e.g. replies to * method calls or received signals. * * @warning dispatching message can result in TQt signals being emitted * before this method returns. In case you just want to make sure * no inbound message is forgotten, call scheduleDispatch() which * will execute the dispatch delayed through the event loop. */ void dispatch() const; /** * @brief Request a delayed check for inbound buffer processing * * Similar to dispatch() but delayed by a single shot timer to ensure * the method has returned before the processing is started. * * If a asynchronous method call is followed by a synchronous call without * returning to the event loop in between, a call to scheduleDispatch() * ensures that a pending reply to the asynchronous call is processed * as soon as possible */ void scheduleDispatch() const; /** * @brief Connects an object to receive D-Bus signals * * This provides a basic access to all D-Bus signals received on this * connection. * For every D-Bus signal processed by the connection object a TQt signal * is emitted and thus delivered to all receiver objects connected * through this method. * * The required slot signature is * @code * void slotname(const TQT_DBusMessage&); * @endcode * * so a suitable receiver could look like this * @code * class DBusSignalReceiver : public TQObject * { * Q_OBJECT * * public slots: * void dbusSignal(const TQT_DBusMessage&); * }; * @endcode * * and would be connected like this * @code * // assuming the following variables * TQT_DBusConnection connection; * DBusSignalReceiver* receiver; * * connection.connect(receiver, TQT_SLOT(dbusSignal(const TQT_DBusMessage&))); * @endcode * * See TQT_DBusProxy::dbusSignal() for a more obvious way of connecting slots. * * @param object the receiver object * @param slot the receiver slot (or signal for signal->signal connections) * * @return @c true if the connection was successfull, otherwise @c false * * @see disconnect() */ bool connect(TQObject* object, const char* slot); /** * @brief Disconnects a given receiver from the D-Bus signal handling * * @param object the receiver object to disconnect from * @param slot the receiver slot (or signal for signal->signal connections) * * @return @c true if the disconnect was successfull, otherwise @c false * * @see connect() */ bool disconnect(TQObject* object, const char* slot); /** * @brief Registers a service object for a given path * * In order to receive method calls over the D-Bus connection the service * objects path within its host application has to be registered with the * connection. See section @ref dbusconventions-objectpath for details. * * Only one objects can be registered for a single object path, i.e. * the path -> object mapping is unambiguous, similar to mapping of * filesystem paths to files. * * If a service object offers more than one interface it is up to the * service implementation if all are implemented in the object path to this * method or if the passed object is just another demultiplexer which * relays the message to the interface implementor. * * @param path the object path to register the object for * @param object the service implementation object for that path * * @return @c true if the given object is now registered for the given path * or @c false if path is empty, object is null or another object * is already registered for this path * * @see unregisterObject() */ bool registerObject(const TQString& path, TQT_DBusObjectBase* object); /** * @brief Unregister a service object on a given path * * Removes any mapping of object path to service object previously * registered by registerObject(). * See section @ref dbusconventions-objectpath for details. * * @warning always(!) unregister a service object before deleting it * * @param path the object path of the object to unregister * * @see registerObject() */ void unregisterObject(const TQString &path); /** * @brief Gets a connection to the session bus * * Convenience overload for creating the default shared connection to the * D-Bus session bus. * * Equivalent to calling addConnection(SessionBus); * * @return a connection handle. Check isConnected() to find out if the * connection attempt has been successfull * * @see addConnection(BusType,const TQString&); */ static TQT_DBusConnection sessionBus(); /** * @brief Gets a connection to the system bus * * Convenience overload for creating the default shared connection to the * D-Bus system bus. * * Equivalent to calling addConnection(SystemBus); * * @return a connection handle. Check isConnected() to find out if the * connection attempt has been successfull * * @see addConnection(BusType,const TQString&); */ static TQT_DBusConnection systemBus(); /** * @brief Add a connection to a bus with a specific bus type * * This is a factory method as it will create a connection for the given * name if its not available yet, but return a previously created * connection for that name if available. * * Depending on the #BusType the D-Bus library will connect to the address * configured for that type, so this is the recommended way to create * connection to D-Bus. * * @code * // Associate the default connection name with a connection to the user's * // session bus * TQT_DBusConnection con = TQT_DBusConnection::addConnection(TQT_DBusConnection::SessionBus); * * // check if we are connected and which uniqueName we got * if (con.isConnected()) * { * tqDebug("Connected to session bus. We got uniqueName %s", * con.uniqueName().local8Bit().data()); * } * @endcode * For the common use cases see also sessionBus() and systemBus() * * @param type the #BusType of the bus to connect to * @param name the name to use for TQT_DBusConnection's connection sharing * * @return a connection handle. Check isConnected() to find out if the * connection attempt has been successfull * * @see closeConnection() */ static TQT_DBusConnection addConnection(BusType type, const TQString &name = default_connection_name); /** * @brief Add a connection to a bus at a specific address * * This is a factory method as it will create a connection for the given * name if its not available yet, but return a previously created * connection for that name if available. * * @note this requires to know the address of a D-Bus daemon to connect to * * @param address the address of the D-Bus daemon. Usually a Unix domain * socket address * @param name the name to use for TQT_DBusConnection's connection sharing * * @return a connection handle. Check isConnected() to find out if the * connection attempt has been successfull * * @see closeConnection() */ static TQT_DBusConnection addConnection(const TQString &address, const TQString &name = default_connection_name); // TODO check why this doesn't close the D-Bus connection /** * @brief Closes a connection with a given name * * Removes the name from the pool of shared connections, i.e. a call to * addConnection() with the same name afterwards will create a new * connection. * * @param name the connection name as used in addConnection() */ static void closeConnection(const TQString &name = default_connection_name); /** * String used as the default parameter for connection names */ QT_STATIC_CONST char *default_connection_name; private: TQT_DBusConnectionPrivate *d; }; #endif