xref: /aosp_15_r20/external/ot-br-posix/src/web/web-service/ot_client.cpp (revision 4a64e381480ef79f0532b2421e44e6ee336b8e0d)
1*4a64e381SAndroid Build Coastguard Worker /*
2*4a64e381SAndroid Build Coastguard Worker  *  Copyright (c) 2020, The OpenThread Authors.
3*4a64e381SAndroid Build Coastguard Worker  *  All rights reserved.
4*4a64e381SAndroid Build Coastguard Worker  *
5*4a64e381SAndroid Build Coastguard Worker  *  Redistribution and use in source and binary forms, with or without
6*4a64e381SAndroid Build Coastguard Worker  *  modification, are permitted provided that the following conditions are met:
7*4a64e381SAndroid Build Coastguard Worker  *  1. Redistributions of source code must retain the above copyright
8*4a64e381SAndroid Build Coastguard Worker  *     notice, this list of conditions and the following disclaimer.
9*4a64e381SAndroid Build Coastguard Worker  *  2. Redistributions in binary form must reproduce the above copyright
10*4a64e381SAndroid Build Coastguard Worker  *     notice, this list of conditions and the following disclaimer in the
11*4a64e381SAndroid Build Coastguard Worker  *     documentation and/or other materials provided with the distribution.
12*4a64e381SAndroid Build Coastguard Worker  *  3. Neither the name of the copyright holder nor the
13*4a64e381SAndroid Build Coastguard Worker  *     names of its contributors may be used to endorse or promote products
14*4a64e381SAndroid Build Coastguard Worker  *     derived from this software without specific prior written permission.
15*4a64e381SAndroid Build Coastguard Worker  *
16*4a64e381SAndroid Build Coastguard Worker  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17*4a64e381SAndroid Build Coastguard Worker  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*4a64e381SAndroid Build Coastguard Worker  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*4a64e381SAndroid Build Coastguard Worker  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20*4a64e381SAndroid Build Coastguard Worker  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21*4a64e381SAndroid Build Coastguard Worker  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22*4a64e381SAndroid Build Coastguard Worker  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23*4a64e381SAndroid Build Coastguard Worker  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24*4a64e381SAndroid Build Coastguard Worker  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25*4a64e381SAndroid Build Coastguard Worker  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26*4a64e381SAndroid Build Coastguard Worker  *  POSSIBILITY OF SUCH DAMAGE.
27*4a64e381SAndroid Build Coastguard Worker  */
28*4a64e381SAndroid Build Coastguard Worker 
29*4a64e381SAndroid Build Coastguard Worker #define OTBR_LOG_TAG "WEB"
30*4a64e381SAndroid Build Coastguard Worker 
31*4a64e381SAndroid Build Coastguard Worker #include "web/web-service/ot_client.hpp"
32*4a64e381SAndroid Build Coastguard Worker 
33*4a64e381SAndroid Build Coastguard Worker #include <openthread/platform/toolchain.h>
34*4a64e381SAndroid Build Coastguard Worker 
35*4a64e381SAndroid Build Coastguard Worker #include <errno.h>
36*4a64e381SAndroid Build Coastguard Worker #include <inttypes.h>
37*4a64e381SAndroid Build Coastguard Worker #include <signal.h>
38*4a64e381SAndroid Build Coastguard Worker #include <stdarg.h>
39*4a64e381SAndroid Build Coastguard Worker #include <stdio.h>
40*4a64e381SAndroid Build Coastguard Worker #include <stdlib.h>
41*4a64e381SAndroid Build Coastguard Worker #include <string.h>
42*4a64e381SAndroid Build Coastguard Worker #include <sys/select.h>
43*4a64e381SAndroid Build Coastguard Worker #include <sys/socket.h>
44*4a64e381SAndroid Build Coastguard Worker #include <sys/un.h>
45*4a64e381SAndroid Build Coastguard Worker #include <unistd.h>
46*4a64e381SAndroid Build Coastguard Worker 
47*4a64e381SAndroid Build Coastguard Worker #include "common/code_utils.hpp"
48*4a64e381SAndroid Build Coastguard Worker #include "common/logging.hpp"
49*4a64e381SAndroid Build Coastguard Worker 
50*4a64e381SAndroid Build Coastguard Worker // Temporary solution before posix platform header files are cleaned up.
51*4a64e381SAndroid Build Coastguard Worker #ifndef OPENTHREAD_POSIX_DAEMON_SOCKET_NAME
52*4a64e381SAndroid Build Coastguard Worker #ifdef __linux__
53*4a64e381SAndroid Build Coastguard Worker #define OPENTHREAD_POSIX_CONFIG_DAEMON_SOCKET_BASENAME "/run/openthread-%s"
54*4a64e381SAndroid Build Coastguard Worker #else
55*4a64e381SAndroid Build Coastguard Worker #define OPENTHREAD_POSIX_CONFIG_DAEMON_SOCKET_BASENAME "/tmp/openthread-%s"
56*4a64e381SAndroid Build Coastguard Worker #endif
57*4a64e381SAndroid Build Coastguard Worker #define OPENTHREAD_POSIX_DAEMON_SOCKET_NAME OPENTHREAD_POSIX_CONFIG_DAEMON_SOCKET_BASENAME ".sock"
58*4a64e381SAndroid Build Coastguard Worker #endif
59*4a64e381SAndroid Build Coastguard Worker 
60*4a64e381SAndroid Build Coastguard Worker namespace otbr {
61*4a64e381SAndroid Build Coastguard Worker namespace Web {
62*4a64e381SAndroid Build Coastguard Worker 
OpenThreadClient(const char * aNetifName)63*4a64e381SAndroid Build Coastguard Worker OpenThreadClient::OpenThreadClient(const char *aNetifName)
64*4a64e381SAndroid Build Coastguard Worker 
65*4a64e381SAndroid Build Coastguard Worker     : mNetifName(aNetifName)
66*4a64e381SAndroid Build Coastguard Worker     , mTimeout(kDefaultTimeout)
67*4a64e381SAndroid Build Coastguard Worker     , mSocket(-1)
68*4a64e381SAndroid Build Coastguard Worker {
69*4a64e381SAndroid Build Coastguard Worker }
70*4a64e381SAndroid Build Coastguard Worker 
~OpenThreadClient(void)71*4a64e381SAndroid Build Coastguard Worker OpenThreadClient::~OpenThreadClient(void)
72*4a64e381SAndroid Build Coastguard Worker {
73*4a64e381SAndroid Build Coastguard Worker     Disconnect();
74*4a64e381SAndroid Build Coastguard Worker }
75*4a64e381SAndroid Build Coastguard Worker 
Disconnect(void)76*4a64e381SAndroid Build Coastguard Worker void OpenThreadClient::Disconnect(void)
77*4a64e381SAndroid Build Coastguard Worker {
78*4a64e381SAndroid Build Coastguard Worker     if (mSocket != -1)
79*4a64e381SAndroid Build Coastguard Worker     {
80*4a64e381SAndroid Build Coastguard Worker         close(mSocket);
81*4a64e381SAndroid Build Coastguard Worker         mSocket = -1;
82*4a64e381SAndroid Build Coastguard Worker     }
83*4a64e381SAndroid Build Coastguard Worker }
84*4a64e381SAndroid Build Coastguard Worker 
Connect(void)85*4a64e381SAndroid Build Coastguard Worker bool OpenThreadClient::Connect(void)
86*4a64e381SAndroid Build Coastguard Worker {
87*4a64e381SAndroid Build Coastguard Worker     struct sockaddr_un sockname;
88*4a64e381SAndroid Build Coastguard Worker     int                ret;
89*4a64e381SAndroid Build Coastguard Worker 
90*4a64e381SAndroid Build Coastguard Worker     mSocket = socket(AF_UNIX, SOCK_STREAM, 0);
91*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(mSocket != -1, perror("socket"); ret = EXIT_FAILURE);
92*4a64e381SAndroid Build Coastguard Worker 
93*4a64e381SAndroid Build Coastguard Worker     memset(&sockname, 0, sizeof(struct sockaddr_un));
94*4a64e381SAndroid Build Coastguard Worker     sockname.sun_family = AF_UNIX;
95*4a64e381SAndroid Build Coastguard Worker     ret = snprintf(sockname.sun_path, sizeof(sockname.sun_path), OPENTHREAD_POSIX_DAEMON_SOCKET_NAME, mNetifName);
96*4a64e381SAndroid Build Coastguard Worker 
97*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(ret >= 0 && static_cast<size_t>(ret) < sizeof(sockname.sun_path), {
98*4a64e381SAndroid Build Coastguard Worker         errno = EINVAL;
99*4a64e381SAndroid Build Coastguard Worker         ret   = -1;
100*4a64e381SAndroid Build Coastguard Worker     });
101*4a64e381SAndroid Build Coastguard Worker 
102*4a64e381SAndroid Build Coastguard Worker     ret = connect(mSocket, reinterpret_cast<const struct sockaddr *>(&sockname), sizeof(struct sockaddr_un));
103*4a64e381SAndroid Build Coastguard Worker 
104*4a64e381SAndroid Build Coastguard Worker     if (ret == -1)
105*4a64e381SAndroid Build Coastguard Worker     {
106*4a64e381SAndroid Build Coastguard Worker         otbrLogErr("OpenThread daemon is not running.");
107*4a64e381SAndroid Build Coastguard Worker     }
108*4a64e381SAndroid Build Coastguard Worker 
109*4a64e381SAndroid Build Coastguard Worker exit:
110*4a64e381SAndroid Build Coastguard Worker     return ret == 0;
111*4a64e381SAndroid Build Coastguard Worker }
112*4a64e381SAndroid Build Coastguard Worker 
DiscardRead(void)113*4a64e381SAndroid Build Coastguard Worker void OpenThreadClient::DiscardRead(void)
114*4a64e381SAndroid Build Coastguard Worker {
115*4a64e381SAndroid Build Coastguard Worker     fd_set  readFdSet;
116*4a64e381SAndroid Build Coastguard Worker     timeval timeout = {0, 0};
117*4a64e381SAndroid Build Coastguard Worker     ssize_t count;
118*4a64e381SAndroid Build Coastguard Worker     int     ret;
119*4a64e381SAndroid Build Coastguard Worker 
120*4a64e381SAndroid Build Coastguard Worker     for (;;)
121*4a64e381SAndroid Build Coastguard Worker     {
122*4a64e381SAndroid Build Coastguard Worker         FD_ZERO(&readFdSet);
123*4a64e381SAndroid Build Coastguard Worker         FD_SET(mSocket, &readFdSet);
124*4a64e381SAndroid Build Coastguard Worker 
125*4a64e381SAndroid Build Coastguard Worker         ret = select(mSocket + 1, &readFdSet, nullptr, nullptr, &timeout);
126*4a64e381SAndroid Build Coastguard Worker         if (ret <= 0)
127*4a64e381SAndroid Build Coastguard Worker         {
128*4a64e381SAndroid Build Coastguard Worker             break;
129*4a64e381SAndroid Build Coastguard Worker         }
130*4a64e381SAndroid Build Coastguard Worker 
131*4a64e381SAndroid Build Coastguard Worker         count = read(mSocket, mBuffer, sizeof(mBuffer));
132*4a64e381SAndroid Build Coastguard Worker         if (count <= 0)
133*4a64e381SAndroid Build Coastguard Worker         {
134*4a64e381SAndroid Build Coastguard Worker             break;
135*4a64e381SAndroid Build Coastguard Worker         }
136*4a64e381SAndroid Build Coastguard Worker     }
137*4a64e381SAndroid Build Coastguard Worker }
138*4a64e381SAndroid Build Coastguard Worker 
Execute(const char * aFormat,...)139*4a64e381SAndroid Build Coastguard Worker char *OpenThreadClient::Execute(const char *aFormat, ...)
140*4a64e381SAndroid Build Coastguard Worker {
141*4a64e381SAndroid Build Coastguard Worker     va_list args;
142*4a64e381SAndroid Build Coastguard Worker     int     ret;
143*4a64e381SAndroid Build Coastguard Worker     char   *rval = nullptr;
144*4a64e381SAndroid Build Coastguard Worker     ssize_t count;
145*4a64e381SAndroid Build Coastguard Worker     size_t  rxLength = 0;
146*4a64e381SAndroid Build Coastguard Worker 
147*4a64e381SAndroid Build Coastguard Worker     DiscardRead();
148*4a64e381SAndroid Build Coastguard Worker 
149*4a64e381SAndroid Build Coastguard Worker     va_start(args, aFormat);
150*4a64e381SAndroid Build Coastguard Worker     ret = vsnprintf(&mBuffer[1], sizeof(mBuffer) - 2, aFormat, args);
151*4a64e381SAndroid Build Coastguard Worker     va_end(args);
152*4a64e381SAndroid Build Coastguard Worker 
153*4a64e381SAndroid Build Coastguard Worker     if (ret < 0)
154*4a64e381SAndroid Build Coastguard Worker     {
155*4a64e381SAndroid Build Coastguard Worker         otbrLogErr("Failed to generate command: %s", strerror(errno));
156*4a64e381SAndroid Build Coastguard Worker         ExitNow();
157*4a64e381SAndroid Build Coastguard Worker     }
158*4a64e381SAndroid Build Coastguard Worker     if (static_cast<size_t>(ret) >= sizeof(mBuffer) - 2)
159*4a64e381SAndroid Build Coastguard Worker     {
160*4a64e381SAndroid Build Coastguard Worker         otbrLogErr("Command exceeds maximum limit: %d", kBufferSize);
161*4a64e381SAndroid Build Coastguard Worker         ExitNow();
162*4a64e381SAndroid Build Coastguard Worker     }
163*4a64e381SAndroid Build Coastguard Worker 
164*4a64e381SAndroid Build Coastguard Worker     mBuffer[0]       = '\n';
165*4a64e381SAndroid Build Coastguard Worker     mBuffer[ret + 1] = '\n';
166*4a64e381SAndroid Build Coastguard Worker     ret += 2;
167*4a64e381SAndroid Build Coastguard Worker 
168*4a64e381SAndroid Build Coastguard Worker     count = write(mSocket, mBuffer, ret);
169*4a64e381SAndroid Build Coastguard Worker 
170*4a64e381SAndroid Build Coastguard Worker     if (count != ret)
171*4a64e381SAndroid Build Coastguard Worker     {
172*4a64e381SAndroid Build Coastguard Worker         mBuffer[ret] = '\0';
173*4a64e381SAndroid Build Coastguard Worker         otbrLogErr("Failed to send command: %s", mBuffer);
174*4a64e381SAndroid Build Coastguard Worker         ExitNow();
175*4a64e381SAndroid Build Coastguard Worker     }
176*4a64e381SAndroid Build Coastguard Worker 
177*4a64e381SAndroid Build Coastguard Worker     for (int i = 0; i < mTimeout; ++i)
178*4a64e381SAndroid Build Coastguard Worker     {
179*4a64e381SAndroid Build Coastguard Worker         fd_set  readFdSet;
180*4a64e381SAndroid Build Coastguard Worker         timeval timeout = {0, 1000};
181*4a64e381SAndroid Build Coastguard Worker         char   *done;
182*4a64e381SAndroid Build Coastguard Worker 
183*4a64e381SAndroid Build Coastguard Worker         FD_ZERO(&readFdSet);
184*4a64e381SAndroid Build Coastguard Worker         FD_SET(mSocket, &readFdSet);
185*4a64e381SAndroid Build Coastguard Worker 
186*4a64e381SAndroid Build Coastguard Worker         ret = select(mSocket + 1, &readFdSet, nullptr, nullptr, &timeout);
187*4a64e381SAndroid Build Coastguard Worker         VerifyOrExit(ret != -1 || errno == EINTR);
188*4a64e381SAndroid Build Coastguard Worker         if (ret <= 0)
189*4a64e381SAndroid Build Coastguard Worker         {
190*4a64e381SAndroid Build Coastguard Worker             continue;
191*4a64e381SAndroid Build Coastguard Worker         }
192*4a64e381SAndroid Build Coastguard Worker 
193*4a64e381SAndroid Build Coastguard Worker         count = read(mSocket, &mBuffer[rxLength], sizeof(mBuffer) - rxLength);
194*4a64e381SAndroid Build Coastguard Worker         VerifyOrExit(count > 0);
195*4a64e381SAndroid Build Coastguard Worker         rxLength += count;
196*4a64e381SAndroid Build Coastguard Worker 
197*4a64e381SAndroid Build Coastguard Worker         mBuffer[rxLength] = '\0';
198*4a64e381SAndroid Build Coastguard Worker         done              = strstr(mBuffer, "Done\r\n> ");
199*4a64e381SAndroid Build Coastguard Worker 
200*4a64e381SAndroid Build Coastguard Worker         if (done != nullptr)
201*4a64e381SAndroid Build Coastguard Worker         {
202*4a64e381SAndroid Build Coastguard Worker             // remove trailing \r\n
203*4a64e381SAndroid Build Coastguard Worker             if (done - mBuffer > 2)
204*4a64e381SAndroid Build Coastguard Worker             {
205*4a64e381SAndroid Build Coastguard Worker                 done[-2] = '\0';
206*4a64e381SAndroid Build Coastguard Worker             }
207*4a64e381SAndroid Build Coastguard Worker 
208*4a64e381SAndroid Build Coastguard Worker             rval = mBuffer;
209*4a64e381SAndroid Build Coastguard Worker             break;
210*4a64e381SAndroid Build Coastguard Worker         }
211*4a64e381SAndroid Build Coastguard Worker     }
212*4a64e381SAndroid Build Coastguard Worker 
213*4a64e381SAndroid Build Coastguard Worker exit:
214*4a64e381SAndroid Build Coastguard Worker     return rval;
215*4a64e381SAndroid Build Coastguard Worker }
216*4a64e381SAndroid Build Coastguard Worker 
Read(const char * aResponse,int aTimeout)217*4a64e381SAndroid Build Coastguard Worker char *OpenThreadClient::Read(const char *aResponse, int aTimeout)
218*4a64e381SAndroid Build Coastguard Worker {
219*4a64e381SAndroid Build Coastguard Worker     ssize_t count    = 0;
220*4a64e381SAndroid Build Coastguard Worker     size_t  rxLength = 0;
221*4a64e381SAndroid Build Coastguard Worker     char   *found;
222*4a64e381SAndroid Build Coastguard Worker     char   *rval = nullptr;
223*4a64e381SAndroid Build Coastguard Worker 
224*4a64e381SAndroid Build Coastguard Worker     for (int i = 0; i < aTimeout; ++i)
225*4a64e381SAndroid Build Coastguard Worker     {
226*4a64e381SAndroid Build Coastguard Worker         count = read(mSocket, &mBuffer[rxLength], sizeof(mBuffer) - rxLength);
227*4a64e381SAndroid Build Coastguard Worker         VerifyOrExit(count > 0);
228*4a64e381SAndroid Build Coastguard Worker         rxLength += count;
229*4a64e381SAndroid Build Coastguard Worker 
230*4a64e381SAndroid Build Coastguard Worker         mBuffer[rxLength] = '\0';
231*4a64e381SAndroid Build Coastguard Worker         found             = strstr(mBuffer, aResponse);
232*4a64e381SAndroid Build Coastguard Worker 
233*4a64e381SAndroid Build Coastguard Worker         if (found != nullptr)
234*4a64e381SAndroid Build Coastguard Worker         {
235*4a64e381SAndroid Build Coastguard Worker             rval = mBuffer;
236*4a64e381SAndroid Build Coastguard Worker             break;
237*4a64e381SAndroid Build Coastguard Worker         }
238*4a64e381SAndroid Build Coastguard Worker     }
239*4a64e381SAndroid Build Coastguard Worker 
240*4a64e381SAndroid Build Coastguard Worker exit:
241*4a64e381SAndroid Build Coastguard Worker     return rval;
242*4a64e381SAndroid Build Coastguard Worker }
243*4a64e381SAndroid Build Coastguard Worker 
Scan(WpanNetworkInfo * aNetworks,int aLength)244*4a64e381SAndroid Build Coastguard Worker int OpenThreadClient::Scan(WpanNetworkInfo *aNetworks, int aLength)
245*4a64e381SAndroid Build Coastguard Worker {
246*4a64e381SAndroid Build Coastguard Worker     char *result;
247*4a64e381SAndroid Build Coastguard Worker     int   rval = 0;
248*4a64e381SAndroid Build Coastguard Worker 
249*4a64e381SAndroid Build Coastguard Worker     mTimeout = 5000;
250*4a64e381SAndroid Build Coastguard Worker     result   = Execute("scan");
251*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(result != nullptr);
252*4a64e381SAndroid Build Coastguard Worker 
253*4a64e381SAndroid Build Coastguard Worker     for (result = strtok(result, "\r\n"); result != nullptr && rval < aLength; result = strtok(nullptr, "\r\n"))
254*4a64e381SAndroid Build Coastguard Worker     {
255*4a64e381SAndroid Build Coastguard Worker         static const char kCliPrompt[] = "> ";
256*4a64e381SAndroid Build Coastguard Worker         char             *cliPrompt;
257*4a64e381SAndroid Build Coastguard Worker         int               matched;
258*4a64e381SAndroid Build Coastguard Worker         int               lqi;
259*4a64e381SAndroid Build Coastguard Worker 
260*4a64e381SAndroid Build Coastguard Worker         // remove prompt
261*4a64e381SAndroid Build Coastguard Worker         if ((cliPrompt = strstr(result, kCliPrompt)) != nullptr)
262*4a64e381SAndroid Build Coastguard Worker         {
263*4a64e381SAndroid Build Coastguard Worker             if (cliPrompt == result)
264*4a64e381SAndroid Build Coastguard Worker             {
265*4a64e381SAndroid Build Coastguard Worker                 result += sizeof(kCliPrompt) - 1;
266*4a64e381SAndroid Build Coastguard Worker             }
267*4a64e381SAndroid Build Coastguard Worker             else
268*4a64e381SAndroid Build Coastguard Worker             {
269*4a64e381SAndroid Build Coastguard Worker                 memmove(cliPrompt, cliPrompt + sizeof(kCliPrompt) - 1, strlen(cliPrompt) - sizeof(kCliPrompt) - 1);
270*4a64e381SAndroid Build Coastguard Worker             }
271*4a64e381SAndroid Build Coastguard Worker         }
272*4a64e381SAndroid Build Coastguard Worker 
273*4a64e381SAndroid Build Coastguard Worker         matched = sscanf(result, "| %hx | %02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx | %hu | %hhd | %d |",
274*4a64e381SAndroid Build Coastguard Worker                          &aNetworks[rval].mPanId, &aNetworks[rval].mHardwareAddress[0],
275*4a64e381SAndroid Build Coastguard Worker                          &aNetworks[rval].mHardwareAddress[1], &aNetworks[rval].mHardwareAddress[2],
276*4a64e381SAndroid Build Coastguard Worker                          &aNetworks[rval].mHardwareAddress[3], &aNetworks[rval].mHardwareAddress[4],
277*4a64e381SAndroid Build Coastguard Worker                          &aNetworks[rval].mHardwareAddress[5], &aNetworks[rval].mHardwareAddress[6],
278*4a64e381SAndroid Build Coastguard Worker                          &aNetworks[rval].mHardwareAddress[7], &aNetworks[rval].mChannel, &aNetworks[rval].mRssi, &lqi);
279*4a64e381SAndroid Build Coastguard Worker 
280*4a64e381SAndroid Build Coastguard Worker         // 15 is the number of output arguments of the last sscanf()
281*4a64e381SAndroid Build Coastguard Worker         if (matched != 12)
282*4a64e381SAndroid Build Coastguard Worker         {
283*4a64e381SAndroid Build Coastguard Worker             continue;
284*4a64e381SAndroid Build Coastguard Worker         }
285*4a64e381SAndroid Build Coastguard Worker 
286*4a64e381SAndroid Build Coastguard Worker         ++rval;
287*4a64e381SAndroid Build Coastguard Worker     }
288*4a64e381SAndroid Build Coastguard Worker 
289*4a64e381SAndroid Build Coastguard Worker     mTimeout = kDefaultTimeout;
290*4a64e381SAndroid Build Coastguard Worker 
291*4a64e381SAndroid Build Coastguard Worker exit:
292*4a64e381SAndroid Build Coastguard Worker     return rval;
293*4a64e381SAndroid Build Coastguard Worker }
294*4a64e381SAndroid Build Coastguard Worker 
FactoryReset(void)295*4a64e381SAndroid Build Coastguard Worker bool OpenThreadClient::FactoryReset(void)
296*4a64e381SAndroid Build Coastguard Worker {
297*4a64e381SAndroid Build Coastguard Worker     const char *result;
298*4a64e381SAndroid Build Coastguard Worker     bool        rval = false;
299*4a64e381SAndroid Build Coastguard Worker #if __APPLE__
300*4a64e381SAndroid Build Coastguard Worker     typedef sig_t sighandler_t;
301*4a64e381SAndroid Build Coastguard Worker #endif
302*4a64e381SAndroid Build Coastguard Worker     sighandler_t handler;
303*4a64e381SAndroid Build Coastguard Worker 
304*4a64e381SAndroid Build Coastguard Worker     // Ignore the expected SIGPIPE signal during daemon reset.
305*4a64e381SAndroid Build Coastguard Worker     handler = signal(SIGPIPE, SIG_IGN);
306*4a64e381SAndroid Build Coastguard Worker     Execute("factoryreset");
307*4a64e381SAndroid Build Coastguard Worker     signal(SIGPIPE, handler);
308*4a64e381SAndroid Build Coastguard Worker     Disconnect();
309*4a64e381SAndroid Build Coastguard Worker     sleep(4);
310*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(rval = Connect());
311*4a64e381SAndroid Build Coastguard Worker 
312*4a64e381SAndroid Build Coastguard Worker     result = Execute("version");
313*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(result != nullptr);
314*4a64e381SAndroid Build Coastguard Worker 
315*4a64e381SAndroid Build Coastguard Worker     rval = strstr(result, "OPENTHREAD") != nullptr;
316*4a64e381SAndroid Build Coastguard Worker 
317*4a64e381SAndroid Build Coastguard Worker exit:
318*4a64e381SAndroid Build Coastguard Worker     return rval;
319*4a64e381SAndroid Build Coastguard Worker }
320*4a64e381SAndroid Build Coastguard Worker 
321*4a64e381SAndroid Build Coastguard Worker } // namespace Web
322*4a64e381SAndroid Build Coastguard Worker } // namespace otbr
323