File: bus.h

package info (click to toggle)
dbus-cpp 5.0.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,208 kB
  • sloc: cpp: 9,427; ansic: 2,012; xml: 1,156; makefile: 14; sh: 2
file content (331 lines) | stat: -rw-r--r-- 10,653 bytes parent folder | download | duplicates (3)
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_