8 #include "../../dbus/bus.h" 16 #include <string_view> 18 #include "../../dbus/matchrule.h" 19 #include "../../dbus/message.h" 20 #include "../../dbus/objectvtable.h" 21 #include "../../event.h" 22 #include "../../flags.h" 23 #include "../../log.h" 24 #include "../../macros.h" 26 #include "message_p.h" 27 #include "objectvtable_p_sdbus.h" 28 #include "sd-bus-wrap.h" 36 ~
BusPrivate() { sd_bus_flush_close_unref(bus_); }
38 sd_bus *bus_ =
nullptr;
42 Bus::Bus(BusType type) : d_ptr(std::make_unique<BusPrivate>()) {
43 decltype(&sd_bus_open) func;
45 case BusType::Session:
46 func = sd_bus_open_user;
49 func = sd_bus_open_system;
55 if (func(&d_ptr->bus_) < 0) {
56 sd_bus_unref(d_ptr->bus_);
57 d_ptr->bus_ =
nullptr;
58 throw std::runtime_error(
"Failed to create dbus connection");
62 Bus::Bus(
const std::string &address) : d_ptr(std::make_unique<BusPrivate>()) {
63 if (sd_bus_new(&d_ptr->bus_) < 0) {
67 if (sd_bus_set_address(d_ptr->bus_, address.c_str()) < 0) {
71 if (sd_bus_set_bus_client(d_ptr->bus_,
true) < 0) {
75 if (sd_bus_start(d_ptr->bus_) < 0) {
81 sd_bus_unref(d_ptr->bus_);
82 d_ptr->bus_ =
nullptr;
83 throw std::runtime_error(
"Failed to create dbus connection");
93 Bus::Bus(
Bus &&other) noexcept : d_ptr(std::move(other.d_ptr)) {}
97 return d->bus_ && sd_bus_is_open(d->bus_) > 0;
101 const char *interface,
const char *member) {
104 auto *msgD = msg.d_func();
105 if (sd_bus_message_new_method_call(d->bus_, &msgD->msg_, destination, path,
106 interface, member) < 0) {
107 msgD->type_ = MessageType::Invalid;
109 msgD->type_ = MessageType::MethodCall;
115 const char *member) {
118 auto *msgD = msg.d_func();
119 int r = sd_bus_message_new_signal(d->bus_, &msgD->msg_, path, interface,
122 msgD->type_ = MessageType::Invalid;
124 msgD->type_ = MessageType::Signal;
135 sd_event *
event =
static_cast<sd_event *
>(loop->nativeHandle());
136 if (sd_bus_attach_event(d->bus_, event, 0) >= 0) {
137 d->eventLoop_ = loop;
141 throw std::invalid_argument(
142 "not support sd-bus with non-sdevent implementation.");
149 sd_bus_detach_event(d->bus_);
150 d->eventLoop_ =
nullptr;
156 return d->eventLoop_;
159 int SDMessageCallback(sd_bus_message *m,
void *userdata,
161 auto *slot =
static_cast<SDSlot *
>(userdata);
166 auto msg = MessagePrivate::fromSDBusMessage(m);
167 auto result = slot->callback_(msg);
168 return result ? 1 : 0;
169 }
catch (
const std::exception &e) {
171 FCITX_ERROR() << e.what();
177 std::unique_ptr<Slot> Bus::addMatch(
const MatchRule &rule,
178 MessageCallback callback) {
180 auto slot = std::make_unique<SDSlot>(std::move(callback));
182 int r = sd_bus_add_match(d->bus_, &sdSlot, rule.rule().c_str(),
183 SDMessageCallback, slot.get());
188 slot->slot_ = sdSlot;
193 std::unique_ptr<Slot> Bus::addFilter(MessageCallback callback) {
195 auto slot = std::make_unique<SDSlot>(std::move(callback));
197 int r = sd_bus_add_filter(d->bus_, &sdSlot, SDMessageCallback, slot.get());
202 slot->slot_ = sdSlot;
207 std::unique_ptr<Slot> Bus::addObject(
const std::string &path,
208 MessageCallback callback) {
210 auto slot = std::make_unique<SDSlot>(std::move(callback));
212 int r = sd_bus_add_object(d->bus_, &sdSlot, path.c_str(), SDMessageCallback,
218 slot->slot_ = sdSlot;
226 auto slot = std::make_unique<SDVTableSlot>(
this, path, interface);
228 int r = sd_bus_add_object_vtable(
229 d->bus_, &sdSlot, path.c_str(), interface.c_str(),
230 vtable.d_func()->toSDBusVTable(&vtable), &vtable);
235 slot->slot_ = sdSlot;
237 vtable.setSlot(slot.release());
241 const char *
Bus::impl() {
return "sdbus"; }
250 int sd_flags = ((flags & RequestNameFlag::ReplaceExisting)
251 ? SD_BUS_NAME_REPLACE_EXISTING
253 ((flags & RequestNameFlag::AllowReplacement)
254 ? SD_BUS_NAME_ALLOW_REPLACEMENT
256 ((flags & RequestNameFlag::Queue) ? SD_BUS_NAME_QUEUE : 0);
257 int r = sd_bus_request_name(d->bus_, name.c_str(), sd_flags);
258 return r >= 0 || r == -EALREADY;
263 return sd_bus_release_name(d->bus_, name.c_str()) >= 0;
267 auto msg = createMethodCall(
"org.freedesktop.DBus",
"/org/freedesktop/DBus",
268 "org.freedesktop.DBus",
"GetNameOwner");
270 auto reply = msg.call(usec);
272 if (reply.type() == dbus::MessageType::Reply) {
273 std::string ownerName;
280 std::unique_ptr<Slot> Bus::serviceOwnerAsync(
const std::string &name,
282 MessageCallback callback) {
283 auto msg = createMethodCall(
"org.freedesktop.DBus",
"/org/freedesktop/DBus",
284 "org.freedesktop.DBus",
"GetNameOwner");
286 return msg.callAsync(usec, std::move(callback));
291 const char *name =
nullptr;
292 if (sd_bus_get_unique_name(d->bus_, &name) < 0) {
300 const char *address =
nullptr;
301 if (sd_bus_get_address(d->bus_, &address) < 0) {
309 sd_bus_flush(d->bus_);
bool addObjectVTable(const std::string &path, const std::string &interface, ObjectVTableBase &vtable)
Register a new object on the dbus.
Basic DBus type of a DBus message.
FCITX_NODISCARD EventLoop * eventLoop() const
Return the attached event loop.
bool requestName(const std::string &name, Flags< RequestNameFlag > flags)
Request the dbus name on the bus.
bool releaseName(const std::string &name)
Release the dbus name.
Bus(const std::string &address)
Connect to given address.
A dbus matching rule to be used with add match.
std::string address()
Return the dbus address being connected to.
A class that represents a connection to the Bus.
Message createMethodCall(const char *destination, const char *path, const char *interface, const char *member)
Create a new method message.
std::string uniqueName()
Return the unique name of current connection.
std::string serviceOwner(const std::string &name, uint64_t usec)
Helper function to query the service owner.
FCITX_NODISCARD void * nativeHandle() const
Return the internal pointer of the implemenation.
const char * implementation() const
Return the name of implementation of event loop.
void flush()
Flush the bus immediately.
void attachEventLoop(EventLoop *loop)
Attach this bus to an event loop.
Class provides bit flag support for Enum.
Message createSignal(const char *path, const char *interface, const char *member)
Create a new signal message.
void detachEventLoop()
Remove this bus from an event loop.
static const char * impl()
Return the name of the compiled implentation of fcitx dbus.
FCITX_NODISCARD bool isOpen() const
Check if the connection is open.