swift
dbusconnection.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2018 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
4 #include "dbusconnection.h"
5 
6 #include <algorithm>
7 #include <cassert>
8 #include <memory>
9 #include <utility>
10 
11 #include "dbusobject.h"
12 
13 namespace XSwiftBus
14 {
15 
16  CDBusConnection::CDBusConnection() { dbus_threads_init_default(); }
17 
18  CDBusConnection::CDBusConnection(DBusConnection *connection)
19  {
20  m_connection.reset(connection);
21  dbus_connection_ref(connection);
22  // Don't exit application, if the connection is disconnected
23  dbus_connection_set_exit_on_disconnect(connection, false);
24  dbus_connection_add_filter(connection, filterDisconnectedFunction, this, nullptr);
25  }
26 
28  {
29  close();
30  if (m_connection) { dispatch(); } // dispatch is virtual, but safe to call in dtor, as it's declared final
31  if (m_dispatcher) { m_dispatcher->remove(this); }
32  }
33 
35  {
36  assert(type == SessionBus);
37  DBusError error;
38  dbus_error_init(&error);
39 
40  DBusBusType dbusBusType;
41  switch (type)
42  {
43  case SessionBus: dbusBusType = DBUS_BUS_SESSION; break;
44  }
45 
46  m_connection.reset(dbus_bus_get_private(dbusBusType, &error));
47  if (dbus_error_is_set(&error))
48  {
49  m_lastError = CDBusError(&error);
50  return false;
51  }
52 
53  // Don't exit application, if the connection is disconnected
54  dbus_connection_set_exit_on_disconnect(m_connection.get(), false);
55  return true;
56  }
57 
59  {
60  assert(dispatcher);
61 
62  m_dispatcher = dispatcher;
63 
64  m_dispatcher->add(this);
65 
66  dbus_connection_set_watch_functions(m_connection.get(), dispatcher->m_watchCallbacks.add,
67  dispatcher->m_watchCallbacks.remove, dispatcher->m_watchCallbacks.toggled,
68  &dispatcher->m_watchCallbacks, nullptr);
69 
70  dbus_connection_set_timeout_functions(
71  m_connection.get(), dispatcher->m_timeoutCallbacks.add, dispatcher->m_timeoutCallbacks.remove,
72  dispatcher->m_timeoutCallbacks.toggled, &dispatcher->m_timeoutCallbacks, nullptr);
73  }
74 
75  void CDBusConnection::requestName(const std::string &name)
76  {
77  DBusError error;
78  dbus_error_init(&error);
79  dbus_bus_request_name(m_connection.get(), name.c_str(), 0, &error);
80  }
81 
83  {
84  return m_connection && dbus_connection_get_is_connected(m_connection.get());
85  }
86 
88  {
89  m_disconnectedCallbacks[obj] = func;
90  }
91 
93  {
94  auto it = m_disconnectedCallbacks.find(obj);
95  if (it == m_disconnectedCallbacks.end()) { return; }
96  m_disconnectedCallbacks.erase(it);
97  }
98 
99  void CDBusConnection::registerObjectPath(CDBusObject *object, const std::string &interfaceName,
100  const std::string &objectPath,
101  const DBusObjectPathVTable &dbusObjectPathVTable)
102  {
103  (void)interfaceName;
104  if (!m_connection) { return; }
105 
106  dbus_connection_try_register_object_path(m_connection.get(), objectPath.c_str(), &dbusObjectPathVTable, object,
107  nullptr);
108  }
109 
111  {
112  if (!isConnected()) { return; }
113  dbus_uint32_t serial = message.getSerial();
114  dbus_connection_send(m_connection.get(), message.m_message, &serial);
115  }
116 
118  {
119  if (m_connection) { dbus_connection_close(m_connection.get()); }
120  }
121 
123  {
124  dbus_connection_ref(m_connection.get());
125  if (dbus_connection_get_dispatch_status(m_connection.get()) == DBUS_DISPATCH_DATA_REMAINS)
126  {
127  while (dbus_connection_dispatch(m_connection.get()) == DBUS_DISPATCH_DATA_REMAINS) {}
128  }
129  dbus_connection_unref(m_connection.get());
130  }
131 
132  void CDBusConnection::setDispatchStatus(DBusConnection *connection, DBusDispatchStatus status)
133  {
134  if (dbus_connection_get_is_connected(connection) == FALSE) { return; }
135 
136  switch (status)
137  {
138  case DBUS_DISPATCH_DATA_REMAINS:
139  // m_dispatcher->add(this);
140  break;
141  case DBUS_DISPATCH_COMPLETE:
142  case DBUS_DISPATCH_NEED_MEMORY: break;
143  }
144  }
145 
146  void CDBusConnection::setDispatchStatus(DBusConnection *connection, DBusDispatchStatus status, void *data)
147  {
148  auto *obj = static_cast<CDBusConnection *>(data);
149  obj->setDispatchStatus(connection, status);
150  }
151 
152  DBusHandlerResult CDBusConnection::filterDisconnectedFunction(DBusConnection *connection, DBusMessage *message,
153  void *data)
154  {
155  (void)connection; // unused
156 
157  auto *obj = static_cast<CDBusConnection *>(data);
158 
159  DBusError err;
160  dbus_error_init(&err);
161 
162  if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected"))
163  {
164  for (auto it = obj->m_disconnectedCallbacks.begin(); it != obj->m_disconnectedCallbacks.end(); ++it)
165  {
166  it->second();
167  }
168  return DBUS_HANDLER_RESULT_HANDLED;
169  }
170  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
171  }
172 
173 } // namespace XSwiftBus
virtual void dispatch() final
Dispatch execution method.
void registerDisconnectedCallback(CDBusObject *obj, DisconnectedCallback func)
Register a disconnected callback.
std::function< void()> DisconnectedCallback
Disconnect Callback.
void requestName(const std::string &name)
Request name to the bus.
void sendMessage(const CDBusMessage &message)
Send message to bus.
void setDispatcher(CDBusDispatcher *dispatcher)
Set dispatcher.
CDBusConnection()
Default constructor.
void close()
Close connection.
bool isConnected() const
Is connected?
void unregisterDisconnectedCallback(CDBusObject *obj)
Register a disconnected callback.
void registerObjectPath(CDBusObject *object, const std::string &interfaceName, const std::string &objectPath, const DBusObjectPathVTable &dbusObjectPathVTable)
Register DBus object with interfaceName and objectPath.
bool connect(BusType type)
Connect to bus.
void add(IDispatchable *dispatchable)
Add dispatchable object.
void remove(IDispatchable *dispatchable)
Remove dispatchable object.
dbus_uint32_t getSerial() const
Get the message serial. This is usally required for reply message.
Definition: dbusmessage.cpp:45
DBus base object.
Definition: dbusobject.h:20
Plugin loaded by X-Plane which publishes a DBus service.
Definition: command.h:14