2 * Copyright (c) 2020, The OpenThread Authors.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
29 #include "dbus/server/dbus_agent.hpp"
31 #include "common/logging.hpp"
32 #include "dbus/common/constants.hpp"
37 const struct timeval DBusAgent::kPollTimeout = {0, 0};
39 DBusAgent::DBusAgent(const std::string &aInterfaceName, otbr::Ncp::ControllerOpenThread *aNcp)
40 : mInterfaceName(aInterfaceName)
45 otbrError DBusAgent::Init(void)
48 otbrError error = OTBR_ERROR_NONE;
50 std::string serverName = OTBR_DBUS_SERVER_PREFIX + mInterfaceName;
52 dbus_error_init(&dbusError);
53 DBusConnection *conn = dbus_bus_get(DBUS_BUS_SYSTEM, &dbusError);
54 mConnection = std::unique_ptr<DBusConnection, std::function<void(DBusConnection *)>>(
55 conn, [](DBusConnection *aConnection) { dbus_connection_unref(aConnection); });
56 VerifyOrExit(mConnection != nullptr, error = OTBR_ERROR_DBUS);
57 dbus_bus_register(mConnection.get(), &dbusError);
59 dbus_bus_request_name(mConnection.get(), serverName.c_str(), DBUS_NAME_FLAG_REPLACE_EXISTING, &dbusError);
60 VerifyOrExit(requestReply == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER ||
61 requestReply == DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER,
62 error = OTBR_ERROR_DBUS);
64 dbus_connection_set_watch_functions(mConnection.get(), AddDBusWatch, RemoveDBusWatch, nullptr, this, nullptr));
65 mThreadObject = std::unique_ptr<DBusThreadObject>(new DBusThreadObject(mConnection.get(), mInterfaceName, mNcp));
66 error = mThreadObject->Init();
68 if (error != OTBR_ERROR_NONE)
70 otbrLog(OTBR_LOG_ERR, "dbus error %s: %s", dbusError.name, dbusError.message);
72 dbus_error_free(&dbusError);
76 dbus_bool_t DBusAgent::AddDBusWatch(struct DBusWatch *aWatch, void *aContext)
78 static_cast<DBusAgent *>(aContext)->mWatches.insert(aWatch);
82 void DBusAgent::RemoveDBusWatch(struct DBusWatch *aWatch, void *aContext)
84 static_cast<DBusAgent *>(aContext)->mWatches.erase(aWatch);
87 void DBusAgent::UpdateFdSet(fd_set & aReadFdSet,
91 struct timeval &aTimeOut)
96 if (dbus_connection_get_dispatch_status(mConnection.get()) == DBUS_DISPATCH_DATA_REMAINS)
101 for (const auto &watch : mWatches)
103 if (!dbus_watch_get_enabled(watch))
108 flags = dbus_watch_get_flags(watch);
109 fd = dbus_watch_get_unix_fd(watch);
116 if (flags & DBUS_WATCH_READABLE)
118 FD_SET(fd, &aReadFdSet);
121 if ((flags & DBUS_WATCH_WRITABLE))
123 FD_SET(fd, &aWriteFdSet);
126 FD_SET(fd, &aErrorFdSet);
135 void DBusAgent::Process(const fd_set &aReadFdSet, const fd_set &aWriteFdSet, const fd_set &aErrorFdSet)
140 for (const auto &watch : mWatches)
142 if (!dbus_watch_get_enabled(watch))
147 flags = dbus_watch_get_flags(watch);
148 fd = dbus_watch_get_unix_fd(watch);
155 if ((flags & DBUS_WATCH_READABLE) && !FD_ISSET(fd, &aReadFdSet))
157 flags &= static_cast<unsigned int>(~DBUS_WATCH_READABLE);
160 if ((flags & DBUS_WATCH_WRITABLE) && !FD_ISSET(fd, &aWriteFdSet))
162 flags &= static_cast<unsigned int>(~DBUS_WATCH_WRITABLE);
165 if (FD_ISSET(fd, &aErrorFdSet))
167 flags |= DBUS_WATCH_ERROR;
170 dbus_watch_handle(watch, flags);
173 while (DBUS_DISPATCH_DATA_REMAINS == dbus_connection_dispatch(mConnection.get()))