Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / ot-br-posix / repo / src / dbus / server / dbus_agent.cpp
1 /*
2  *    Copyright (c) 2020, The OpenThread Authors.
3  *    All rights reserved.
4  *
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.
15  *
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.
27  */
28
29 #include "dbus/server/dbus_agent.hpp"
30
31 #include "common/logging.hpp"
32 #include "dbus/common/constants.hpp"
33
34 namespace otbr {
35 namespace DBus {
36
37 const struct timeval DBusAgent::kPollTimeout = {0, 0};
38
39 DBusAgent::DBusAgent(const std::string &aInterfaceName, otbr::Ncp::ControllerOpenThread *aNcp)
40     : mInterfaceName(aInterfaceName)
41     , mNcp(aNcp)
42 {
43 }
44
45 otbrError DBusAgent::Init(void)
46 {
47     DBusError   dbusError;
48     otbrError   error = OTBR_ERROR_NONE;
49     int         requestReply;
50     std::string serverName = OTBR_DBUS_SERVER_PREFIX + mInterfaceName;
51
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);
58     requestReply =
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);
63     VerifyOrExit(
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();
67 exit:
68     if (error != OTBR_ERROR_NONE)
69     {
70         otbrLog(OTBR_LOG_ERR, "dbus error %s: %s", dbusError.name, dbusError.message);
71     }
72     dbus_error_free(&dbusError);
73     return error;
74 }
75
76 dbus_bool_t DBusAgent::AddDBusWatch(struct DBusWatch *aWatch, void *aContext)
77 {
78     static_cast<DBusAgent *>(aContext)->mWatches.insert(aWatch);
79     return TRUE;
80 }
81
82 void DBusAgent::RemoveDBusWatch(struct DBusWatch *aWatch, void *aContext)
83 {
84     static_cast<DBusAgent *>(aContext)->mWatches.erase(aWatch);
85 }
86
87 void DBusAgent::UpdateFdSet(fd_set &        aReadFdSet,
88                             fd_set &        aWriteFdSet,
89                             fd_set &        aErrorFdSet,
90                             int &           aMaxFd,
91                             struct timeval &aTimeOut)
92 {
93     unsigned int flags;
94     int          fd;
95
96     if (dbus_connection_get_dispatch_status(mConnection.get()) == DBUS_DISPATCH_DATA_REMAINS)
97     {
98         aTimeOut = {0, 0};
99     }
100
101     for (const auto &watch : mWatches)
102     {
103         if (!dbus_watch_get_enabled(watch))
104         {
105             continue;
106         }
107
108         flags = dbus_watch_get_flags(watch);
109         fd    = dbus_watch_get_unix_fd(watch);
110
111         if (fd < 0)
112         {
113             continue;
114         }
115
116         if (flags & DBUS_WATCH_READABLE)
117         {
118             FD_SET(fd, &aReadFdSet);
119         }
120
121         if ((flags & DBUS_WATCH_WRITABLE))
122         {
123             FD_SET(fd, &aWriteFdSet);
124         }
125
126         FD_SET(fd, &aErrorFdSet);
127
128         if (fd > aMaxFd)
129         {
130             aMaxFd = fd;
131         }
132     }
133 }
134
135 void DBusAgent::Process(const fd_set &aReadFdSet, const fd_set &aWriteFdSet, const fd_set &aErrorFdSet)
136 {
137     unsigned int flags;
138     int          fd;
139
140     for (const auto &watch : mWatches)
141     {
142         if (!dbus_watch_get_enabled(watch))
143         {
144             continue;
145         }
146
147         flags = dbus_watch_get_flags(watch);
148         fd    = dbus_watch_get_unix_fd(watch);
149
150         if (fd < 0)
151         {
152             continue;
153         }
154
155         if ((flags & DBUS_WATCH_READABLE) && !FD_ISSET(fd, &aReadFdSet))
156         {
157             flags &= static_cast<unsigned int>(~DBUS_WATCH_READABLE);
158         }
159
160         if ((flags & DBUS_WATCH_WRITABLE) && !FD_ISSET(fd, &aWriteFdSet))
161         {
162             flags &= static_cast<unsigned int>(~DBUS_WATCH_WRITABLE);
163         }
164
165         if (FD_ISSET(fd, &aErrorFdSet))
166         {
167             flags |= DBUS_WATCH_ERROR;
168         }
169
170         dbus_watch_handle(watch, flags);
171     }
172
173     while (DBUS_DISPATCH_DATA_REMAINS == dbus_connection_dispatch(mConnection.get()))
174         ;
175 }
176
177 } // namespace DBus
178 } // namespace otbr