• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <assert.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 
34 #include <memory>
35 
36 #include <dbus/dbus.h>
37 #include <unistd.h>
38 
39 #include "common/code_utils.hpp"
40 #include "dbus/client/thread_api_dbus.hpp"
41 #include "dbus/common/constants.hpp"
42 
43 using otbr::DBus::ActiveScanResult;
44 using otbr::DBus::ClientError;
45 using otbr::DBus::DeviceRole;
46 using otbr::DBus::EnergyScanResult;
47 using otbr::DBus::ExternalRoute;
48 using otbr::DBus::Ip6Prefix;
49 using otbr::DBus::LinkModeConfig;
50 using otbr::DBus::OnMeshPrefix;
51 using otbr::DBus::SrpServerInfo;
52 using otbr::DBus::ThreadApiDBus;
53 using otbr::DBus::TxtEntry;
54 
55 #if OTBR_ENABLE_DNSSD_DISCOVERY_PROXY
56 using otbr::DBus::DnssdCounters;
57 #endif
58 
59 #define TEST_ASSERT(x)                                              \
60     do                                                              \
61     {                                                               \
62         if (!(x))                                                   \
63         {                                                           \
64             printf("Assert failed at %s:%d\n", __FILE__, __LINE__); \
65             exit(EXIT_FAILURE);                                     \
66         }                                                           \
67     } while (false)
68 
69 struct DBusConnectionDeleter
70 {
operator ()DBusConnectionDeleter71     void operator()(DBusConnection *aConnection) { dbus_connection_unref(aConnection); }
72 };
73 
74 using UniqueDBusConnection = std::unique_ptr<DBusConnection, DBusConnectionDeleter>;
75 
operator ==(const otbr::DBus::Ip6Prefix & aLhs,const otbr::DBus::Ip6Prefix & aRhs)76 static bool operator==(const otbr::DBus::Ip6Prefix &aLhs, const otbr::DBus::Ip6Prefix &aRhs)
77 {
78     bool prefixDataEquality = (aLhs.mPrefix.size() == aRhs.mPrefix.size()) &&
79                               (memcmp(&aLhs.mPrefix[0], &aRhs.mPrefix[0], aLhs.mPrefix.size()) == 0);
80 
81     return prefixDataEquality && aLhs.mLength == aRhs.mLength;
82 }
83 
CheckExternalRoute(ThreadApiDBus * aApi,const Ip6Prefix & aPrefix)84 static void CheckExternalRoute(ThreadApiDBus *aApi, const Ip6Prefix &aPrefix)
85 {
86     ExternalRoute              route = {};
87     std::vector<ExternalRoute> externalRouteTable;
88 
89     route.mPrefix     = aPrefix;
90     route.mStable     = true;
91     route.mPreference = 0;
92 
93     TEST_ASSERT(aApi->AddExternalRoute(route) == OTBR_ERROR_NONE);
94     sleep(10);
95     TEST_ASSERT(aApi->GetExternalRoutes(externalRouteTable) == OTBR_ERROR_NONE);
96     TEST_ASSERT(externalRouteTable.size() == 1);
97     TEST_ASSERT(externalRouteTable[0].mPrefix == aPrefix);
98     TEST_ASSERT(externalRouteTable[0].mPreference == 0);
99     TEST_ASSERT(externalRouteTable[0].mStable);
100     TEST_ASSERT(externalRouteTable[0].mNextHopIsThisDevice);
101 
102     TEST_ASSERT(aApi->RemoveExternalRoute(aPrefix) == OTBR_ERROR_NONE);
103     sleep(10);
104     TEST_ASSERT(aApi->GetExternalRoutes(externalRouteTable) == OTBR_ERROR_NONE);
105     TEST_ASSERT(externalRouteTable.empty());
106 }
107 
CheckOnMeshPrefix(ThreadApiDBus * aApi)108 static void CheckOnMeshPrefix(ThreadApiDBus *aApi)
109 {
110     OnMeshPrefix              prefix = {};
111     std::vector<OnMeshPrefix> onMeshPrefixes;
112 
113     prefix.mPrefix.mPrefix = {0xfd, 0xee, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
114     prefix.mPrefix.mLength = 64;
115 
116     prefix.mPreference = 0;
117     prefix.mStable     = true;
118 
119     TEST_ASSERT(aApi->AddOnMeshPrefix(prefix) == OTBR_ERROR_NONE);
120     sleep(10);
121     TEST_ASSERT(aApi->GetOnMeshPrefixes(onMeshPrefixes) == OTBR_ERROR_NONE);
122     TEST_ASSERT(onMeshPrefixes.size() == 1);
123     TEST_ASSERT(onMeshPrefixes[0].mPrefix == prefix.mPrefix);
124     TEST_ASSERT(onMeshPrefixes[0].mPreference == 0);
125     TEST_ASSERT(onMeshPrefixes[0].mStable);
126 
127     TEST_ASSERT(aApi->RemoveOnMeshPrefix(prefix.mPrefix) == OTBR_ERROR_NONE);
128     sleep(10);
129     TEST_ASSERT(aApi->GetOnMeshPrefixes(onMeshPrefixes) == OTBR_ERROR_NONE);
130     TEST_ASSERT(onMeshPrefixes.empty());
131 }
132 
CheckSrpServerInfo(ThreadApiDBus * aApi)133 void CheckSrpServerInfo(ThreadApiDBus *aApi)
134 {
135     SrpServerInfo srpServerInfo;
136 
137     TEST_ASSERT(aApi->GetSrpServerInfo(srpServerInfo) == OTBR_ERROR_NONE);
138     TEST_ASSERT(srpServerInfo.mState == otbr::DBus::OTBR_SRP_SERVER_STATE_RUNNING);
139     TEST_ASSERT(srpServerInfo.mPort != 0);
140     TEST_ASSERT(srpServerInfo.mHosts.mFreshCount == 0);
141     TEST_ASSERT(srpServerInfo.mHosts.mDeletedCount == 0);
142     TEST_ASSERT(srpServerInfo.mHosts.mLeaseTimeTotal == 0);
143     TEST_ASSERT(srpServerInfo.mHosts.mKeyLeaseTimeTotal == 0);
144     TEST_ASSERT(srpServerInfo.mHosts.mRemainingLeaseTimeTotal == 0);
145     TEST_ASSERT(srpServerInfo.mHosts.mRemainingKeyLeaseTimeTotal == 0);
146     TEST_ASSERT(srpServerInfo.mServices.mFreshCount == 0);
147     TEST_ASSERT(srpServerInfo.mServices.mDeletedCount == 0);
148     TEST_ASSERT(srpServerInfo.mServices.mLeaseTimeTotal == 0);
149     TEST_ASSERT(srpServerInfo.mServices.mKeyLeaseTimeTotal == 0);
150     TEST_ASSERT(srpServerInfo.mServices.mRemainingLeaseTimeTotal == 0);
151     TEST_ASSERT(srpServerInfo.mServices.mRemainingKeyLeaseTimeTotal == 0);
152     TEST_ASSERT(srpServerInfo.mResponseCounters.mSuccess == 0);
153     TEST_ASSERT(srpServerInfo.mResponseCounters.mServerFailure == 0);
154     TEST_ASSERT(srpServerInfo.mResponseCounters.mFormatError == 0);
155     TEST_ASSERT(srpServerInfo.mResponseCounters.mNameExists == 0);
156     TEST_ASSERT(srpServerInfo.mResponseCounters.mRefused == 0);
157     TEST_ASSERT(srpServerInfo.mResponseCounters.mOther == 0);
158 }
159 
CheckDnssdCounters(ThreadApiDBus * aApi)160 void CheckDnssdCounters(ThreadApiDBus *aApi)
161 {
162     OTBR_UNUSED_VARIABLE(aApi);
163 #if OTBR_ENABLE_DNSSD_DISCOVERY_PROXY
164     otbr::DBus::DnssdCounters dnssdCounters;
165 
166     TEST_ASSERT(aApi->GetDnssdCounters(dnssdCounters) == OTBR_ERROR_NONE);
167     TEST_ASSERT(dnssdCounters.mSuccessResponse == 0);
168     TEST_ASSERT(dnssdCounters.mServerFailureResponse == 0);
169     TEST_ASSERT(dnssdCounters.mFormatErrorResponse == 0);
170     TEST_ASSERT(dnssdCounters.mNameErrorResponse == 0);
171     TEST_ASSERT(dnssdCounters.mNotImplementedResponse == 0);
172     TEST_ASSERT(dnssdCounters.mOtherResponse == 0);
173     TEST_ASSERT(dnssdCounters.mResolvedBySrp == 0);
174 #endif
175 }
176 
CheckMdnsInfo(ThreadApiDBus * aApi)177 void CheckMdnsInfo(ThreadApiDBus *aApi)
178 {
179     otbr::MdnsTelemetryInfo mdnsInfo;
180 
181     TEST_ASSERT(aApi->GetMdnsTelemetryInfo(mdnsInfo) == OTBR_ERROR_NONE);
182 
183     TEST_ASSERT(mdnsInfo.mServiceRegistrations.mSuccess > 0);
184     TEST_ASSERT(mdnsInfo.mServiceRegistrationEmaLatency > 0);
185 }
186 
main()187 int main()
188 {
189     DBusError                      error;
190     UniqueDBusConnection           connection;
191     std::unique_ptr<ThreadApiDBus> api;
192     uint64_t                       extpanid = 0xdead00beaf00cafe;
193     std::string                    region;
194     uint32_t                       scanDuration = 1000; // 1s for each channel
195     bool                           stepDone     = false;
196 
197     dbus_error_init(&error);
198     connection = UniqueDBusConnection(dbus_bus_get(DBUS_BUS_SYSTEM, &error));
199 
200     VerifyOrExit(connection != nullptr);
201 
202     VerifyOrExit(dbus_bus_register(connection.get(), &error) == true);
203 
204     api = std::unique_ptr<ThreadApiDBus>(new ThreadApiDBus(connection.get()));
205 
206     api->AddDeviceRoleHandler(
207         [](DeviceRole aRole) { printf("Device role changed to %d\n", static_cast<uint8_t>(aRole)); });
208 
209     TEST_ASSERT(api->SetRadioRegion("US") == ClientError::ERROR_NONE);
210     TEST_ASSERT(api->GetRadioRegion(region) == ClientError::ERROR_NONE);
211     TEST_ASSERT(region == "US");
212 
213     api->EnergyScan(scanDuration, [&stepDone](const std::vector<EnergyScanResult> &aResult) {
214         TEST_ASSERT(!aResult.empty());
215         printf("Energy Scan:\n");
216         for (auto &result : aResult)
217         {
218             printf("channel %d rssi %d\n", result.mChannel, result.mMaxRssi);
219         }
220 
221         stepDone = true;
222     });
223 
224     while (!stepDone)
225     {
226         dbus_connection_read_write_dispatch(connection.get(), 0);
227     }
228 
229     stepDone = false;
230 
231     api->Scan([&api, extpanid, &stepDone](const std::vector<ActiveScanResult> &aResult) {
232         LinkModeConfig       cfg        = {true, false, true};
233         std::vector<uint8_t> networkKey = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
234                                            0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
235         uint16_t             channel    = 11;
236 
237         for (auto &&result : aResult)
238         {
239             printf("channel %d rssi %d\n", result.mChannel, result.mRssi);
240         }
241 
242         api->SetLinkMode(cfg);
243         api->GetLinkMode(cfg);
244         printf("LinkMode %d %d %d\n", cfg.mRxOnWhenIdle, cfg.mDeviceType, cfg.mNetworkData);
245 
246         cfg.mDeviceType = true;
247         api->SetLinkMode(cfg);
248 
249         api->Attach("Test", 0x3456, extpanid, networkKey, {}, 1 << channel,
250                     [&api, channel, extpanid, &stepDone](ClientError aError) {
251                         printf("Attach result %d\n", static_cast<int>(aError));
252                         sleep(20);
253                         uint64_t             extpanidCheck;
254                         std::vector<uint8_t> activeDataset;
255 
256                         if (aError == OTBR_ERROR_NONE)
257                         {
258                             std::string                           name;
259                             uint64_t                              extAddress = 0;
260                             uint16_t                              rloc16     = 0xffff;
261                             std::vector<uint8_t>                  networkData;
262                             std::vector<uint8_t>                  stableNetworkData;
263                             int8_t                                rssi;
264                             int8_t                                txPower;
265                             std::vector<otbr::DBus::ChildInfo>    childTable;
266                             std::vector<otbr::DBus::NeighborInfo> neighborTable;
267                             uint32_t                              partitionId;
268                             uint16_t                              channelResult;
269 
270                             TEST_ASSERT(api->GetChannel(channelResult) == OTBR_ERROR_NONE);
271                             TEST_ASSERT(channelResult == channel);
272                             TEST_ASSERT(api->GetNetworkName(name) == OTBR_ERROR_NONE);
273                             TEST_ASSERT(api->GetExtPanId(extpanidCheck) == OTBR_ERROR_NONE);
274                             TEST_ASSERT(api->GetRloc16(rloc16) == OTBR_ERROR_NONE);
275                             TEST_ASSERT(api->GetExtendedAddress(extAddress) == OTBR_ERROR_NONE);
276                             TEST_ASSERT(api->GetNetworkData(networkData) == OTBR_ERROR_NONE);
277                             TEST_ASSERT(api->GetStableNetworkData(stableNetworkData) == OTBR_ERROR_NONE);
278                             TEST_ASSERT(api->GetChildTable(childTable) == OTBR_ERROR_NONE);
279                             TEST_ASSERT(api->GetNeighborTable(neighborTable) == OTBR_ERROR_NONE);
280                             printf("neighborTable size %zu\n", neighborTable.size());
281                             printf("childTable size %zu\n", childTable.size());
282                             TEST_ASSERT(neighborTable.size() == 1);
283                             TEST_ASSERT(childTable.size() == 1);
284                             TEST_ASSERT(api->GetPartitionId(partitionId) == OTBR_ERROR_NONE);
285                             TEST_ASSERT(api->GetInstantRssi(rssi) == OTBR_ERROR_NONE);
286                             TEST_ASSERT(api->GetRadioTxPower(txPower) == OTBR_ERROR_NONE);
287                             TEST_ASSERT(api->GetActiveDatasetTlvs(activeDataset) == OTBR_ERROR_NONE);
288                             CheckSrpServerInfo(api.get());
289                             CheckMdnsInfo(api.get());
290                             CheckDnssdCounters(api.get());
291                             api->FactoryReset(nullptr);
292                             TEST_ASSERT(api->GetNetworkName(name) == OTBR_ERROR_NONE);
293                             TEST_ASSERT(rloc16 != 0xffff);
294                             TEST_ASSERT(extAddress != 0);
295                             TEST_ASSERT(!networkData.empty());
296                             TEST_ASSERT(api->GetNeighborTable(neighborTable) == OTBR_ERROR_NONE);
297                             TEST_ASSERT(neighborTable.empty());
298                         }
299                         if (aError != OTBR_ERROR_NONE || extpanidCheck != extpanid)
300                         {
301                             exit(-1);
302                         }
303                         TEST_ASSERT(api->SetActiveDatasetTlvs(activeDataset) == OTBR_ERROR_NONE);
304                         api->Attach([&api, channel, extpanid, &stepDone](ClientError aErr) {
305                             uint8_t                routerId;
306                             otbr::DBus::LeaderData leaderData;
307                             uint8_t                leaderWeight;
308                             uint16_t               channelResult;
309                             uint64_t               extpanidCheck;
310                             Ip6Prefix              prefix;
311                             std::vector<TxtEntry>  updatedTxtEntries{TxtEntry{"B", {97, 98, 99}}};
312 
313                             prefix.mPrefix = {0xfd, 0xcd, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
314                             prefix.mLength = 64;
315 
316                             TEST_ASSERT(aErr == ClientError::ERROR_NONE);
317                             TEST_ASSERT(api->GetChannel(channelResult) == OTBR_ERROR_NONE);
318                             TEST_ASSERT(channelResult == channel);
319                             TEST_ASSERT(api->GetExtPanId(extpanidCheck) == OTBR_ERROR_NONE);
320                             TEST_ASSERT(extpanidCheck == extpanid);
321 
322                             TEST_ASSERT(api->GetLocalLeaderWeight(leaderWeight) == OTBR_ERROR_NONE);
323                             TEST_ASSERT(api->GetLeaderData(leaderData) == OTBR_ERROR_NONE);
324                             TEST_ASSERT(api->GetRouterId(routerId) == OTBR_ERROR_NONE);
325                             TEST_ASSERT(routerId == leaderData.mLeaderRouterId);
326 
327                             TEST_ASSERT(api->UpdateVendorMeshCopTxtEntries(updatedTxtEntries) == OTBR_ERROR_NONE);
328 
329                             CheckExternalRoute(api.get(), prefix);
330                             CheckOnMeshPrefix(api.get());
331 
332                             api->FactoryReset(nullptr);
333                             TEST_ASSERT(api->JoinerStart("ABCDEF", "", "", "", "", "", nullptr) ==
334                                         ClientError::OT_ERROR_NOT_FOUND);
335                             TEST_ASSERT(api->JoinerStart(
336                                             "ABCDEF", "", "", "", "", "", [&api, &stepDone](ClientError aJoinError) {
337                                                 DeviceRole deviceRole;
338 
339                                                 TEST_ASSERT(aJoinError == ClientError::OT_ERROR_NOT_FOUND);
340 
341                                                 api->FactoryReset(nullptr);
342                                                 api->GetDeviceRole(deviceRole);
343                                                 TEST_ASSERT(deviceRole == otbr::DBus::OTBR_DEVICE_ROLE_DISABLED);
344 
345                                                 stepDone = true;
346                                             }) == ClientError::ERROR_NONE);
347                         });
348                     });
349     });
350 
351     while (!stepDone)
352     {
353         dbus_connection_read_write_dispatch(connection.get(), 0);
354     }
355 
356 exit:
357     dbus_error_free(&error);
358     return 0;
359 };
360