1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
|
/*
* Copyright © 2012 Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 3,
* as published by the Free Software Foundation.
*
* 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authored by: Thomas Voß <thomas.voss@canonical.com>
*/
#ifndef CORE_DBUS_BUS_H_
#define CORE_DBUS_BUS_H_
#include <core/dbus/error.h>
#include <core/dbus/executor.h>
#include <core/dbus/message.h>
#include <core/dbus/message_factory.h>
#include <core/dbus/message_router.h>
#include <core/dbus/pending_call.h>
#include <core/dbus/visibility.h>
#include <core/dbus/well_known_bus.h>
#include <core/dbus/types/object_path.h>
#include <cstring>
#include <chrono>
#include <functional>
#include <iostream>
#include <memory>
#include <map>
#include <mutex>
#include <stdexcept>
#include <sstream>
#include <string>
#include <thread>
#include <tuple>
namespace core
{
namespace dbus
{
class MatchRule;
class Object;
/**
* @brief The Bus class constitutes a very thin wrapper and the starting
* point to expose low-level DBus functionality for internal purposes.
*/
class ORG_FREEDESKTOP_DBUS_DLL_PUBLIC Bus
{
public:
typedef std::shared_ptr<Bus> Ptr;
/**
* @brief The RequestNameFlag enum lists possible behavior when trying to acquire name on the bus.
*/
enum class RequestNameFlag
{
not_set = 0,
allow_replacement = 1 << 0, ///< Allow for later replacement by another service implementation.
replace_existing = 1 << 1, ///< Replace any existing instance on the bus.
do_not_queue = 1 << 2 ///< Blocking wait for service name to be acquired.
};
/** @brief Describes a name on the bus. */
class Name
{
public:
Name(const Name&) = delete;
Name(Name&& rhs);
Name& operator=(Name&& rhs);
/**
* @brief as_string returns a string presentation of the name.
*/
const std::string& as_string() const;
private:
friend class Bus;
Name(const std::string& name);
std::string name;
};
/**
* @brief default_request_name_flags returns defaults flags when acquiring a name on the bus.
*/
static RequestNameFlag default_request_name_flags();
/**
* @brief The Errors struct summarizes exceptions that are thrown by Bus functions.
*/
struct Errors
{
Errors() = delete;
/**
* @brief The AlreadyOwner exception if this process already owns the name on the bus.
*/
struct AlreadyOwner : public std::runtime_error
{
inline AlreadyOwner()
: std::runtime_error(
"This process already owns the name on the bus.")
{
}
};
/**
* @brief The AlreadyOwned exception is thrown if this process already owns the name on the bus.
*/
struct AlreadyOwned : public std::runtime_error
{
inline AlreadyOwned()
: std::runtime_error(
"The name is already owned on the bus.")
{
}
};
/**
* @brief The NoMemory exception is thrown if an operation failed due to a lack of memory.
*/
struct NoMemory : public std::runtime_error
{
inline NoMemory()
: std::runtime_error(
"Not enough memory to complete operation.")
{
}
};
/**
* @brief The ObjectPathInUse exception is thrown if a path is already owned.
*/
struct ObjectPathInUse
: public std::runtime_error
{
inline ObjectPathInUse()
: std::runtime_error(
"Object path is already in use.")
{
}
};
};
/** @brief Routing of messages based on their type. */
typedef MessageRouter<Message::Type> MessageTypeRouter;
/** @brief Routing of signals based on a tuple of interface and member name. */
typedef MessageRouter<types::ObjectPath> SignalRouter;
/**
* @brief The MessageHandlerResult enum summarizes possible replies of a MessageHandler.
*/
enum class MessageHandlerResult
{
handled = DBUS_HANDLER_RESULT_HANDLED, ///< Message has had its effect - no need to run more handlers.
not_yet_handled = DBUS_HANDLER_RESULT_NOT_YET_HANDLED, ///< Message has not had any effect - see if other handlers want it.
need_memory = DBUS_HANDLER_RESULT_NEED_MEMORY ///< Need more memory, please try again later with more memory.
};
/** @brief Function signature for handling a message. */
typedef std::function<MessageHandlerResult(const Message::Ptr& msg)> MessageHandler;
/**
* @brief Constructs an instance of Bus and connected to the bus specified by address.
* @param address The address of the bus to connect to.
*/
explicit Bus(const std::string& address);
/**
* @brief Creates a connection to a well-known bus. The implementation takes care of setting up thread-safety flags for DBus.
* @param bus The well-known bus the instance should connect to.
*/
explicit Bus(WellKnownBus bus);
// A Bus instance is not copy-able.
Bus(const Bus&) = delete;
/**
* @brief Disconnects from the bus and releases the connection corresponding to this instance.
*/
~Bus() noexcept;
Bus& operator=(const Bus&) = delete;
bool operator==(const Bus&) const = delete;
/**
* @brief Provides access to a bus-specific message factory.
*/
const std::shared_ptr<MessageFactory> message_factory();
/**
* @brief Attempts to own the given name on the bus.
* @throw Bus::Errors::AlreadyOwner if this process already owns the name.
* @throw Bus::Errors::AlreadyOwned if the name is already owned on the bus.
* @return A unique instance if the ownership request completed successfully.
*/
Name request_name_on_bus(
const std::string& name,
RequestNameFlag flags);
/**
* @brief Releases the previously owned name.
* @param name The name to release.
*/
void release_name_on_bus(Name&& name);
/**
* @brief Sends a raw DBus message over this DBus connection.
* @param msg The message to send, must not be null.
* @return A reply serial.
* @throw std::runtime_error in case of errors.
*/
uint32_t send(const std::shared_ptr<Message>& msg);
/**
* @brief Invokes a function and blocks for a specified amount of time waiting for a result.
* @param msg The method call.
* @param milliseconds The timeout.
* @return The reply message or null in case of errors.
* @throw std::runtime_error if a timeout occurs.
*/
std::shared_ptr<Message> send_with_reply_and_block_for_at_most(
const std::shared_ptr<Message>& msg,
const std::chrono::milliseconds& milliseconds);
/**
* @brief Invokes a function, returning a waitable pending call that times out after the specified time period.
* @param msg The method call.
* @param timeout The timeout.
* @return The waitable, pending call for this method invocation.
*/
PendingCall::Ptr send_with_reply_and_timeout(
const std::shared_ptr<Message>& msg,
const std::chrono::milliseconds& timeout);
/**
* @brief Installs a match rule to the underlying DBus connection.
* @param rule The match rule to be installed, has to be a valid match rule.
*/
void add_match(const MatchRule& rule);
/**
* @brief Uninstalls a match rule to the underlying DBus connection.
* @param rule The match rule to be uninstalled.
*/
void remove_match(const MatchRule& rule);
/**
* @brief Checks if the given name is owned on this bus connection.
* @param name The name to check ownership for.
* @return true if the name is already owned, false otherwise.
*/
bool has_owner_for_name(const std::string& name);
/**
* @brief Installs an executor for this bus connection, enabling signal and method call delivery.
* @param e The executor instance, must not be null.
*/
void install_executor(const Executor::Ptr& e);
/**
* @brief Stops signal and method call delivery, i.e., stops the underlying executor if any.
*/
void stop();
/**
* @brief Starts signal and method call delivery, i.e., starts the underlying executor if any.
*/
void run();
/**
* @brief Provides mutable access to the contained signal router.
*/
SignalRouter& access_signal_router();
/**
* @brief Provides raw, unmanaged access to the underlying DBus connection.
*/
DBusConnection* raw() const;
/**
* @brief register_object_for_path makes the given object known for the path on the bus.
* @throw Bus::Errors::NoMemory if not enough memory.
* @throw Bus::Errors::ObjectPathInUse if path is already used.
* @param path The path to make the object known for on the bus.
* @param object The object to make known
*/
void register_object_for_path(
const types::ObjectPath& path,
const std::shared_ptr<Object>& object);
/**
* @brief unregister_object_path removes the object known under the given name from the bus.
* @throw Bus::Errors::NoMemory if not enough memory.
* @param path The path to remove from the bus.
*/
void unregister_object_path(
const types::ObjectPath& path);
/**
* @brief Hands over a message to the internal message and signal routers.
*/
MessageHandlerResult handle_message(const Message::Ptr& msg);
private:
struct Private;
std::unique_ptr<Private> d;
};
/** @brief Enables usage of RequestNameFlag as a bitfield. */
inline Bus::RequestNameFlag operator|(Bus::RequestNameFlag lhs, Bus::RequestNameFlag rhs)
{
return static_cast<Bus::RequestNameFlag>(
static_cast<unsigned int>(lhs) |
static_cast<unsigned int>(rhs));
}
}
}
#endif // CORE_DBUS_BUS_H_
|