xref: /aosp_15_r20/external/ot-br-posix/src/web/web-service/wpan_service.cpp (revision 4a64e381480ef79f0532b2421e44e6ee336b8e0d)
1*4a64e381SAndroid Build Coastguard Worker /*
2*4a64e381SAndroid Build Coastguard Worker  *  Copyright (c) 2017, 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 /**
30*4a64e381SAndroid Build Coastguard Worker  * @file
31*4a64e381SAndroid Build Coastguard Worker  *   This file implements the wpan controller service
32*4a64e381SAndroid Build Coastguard Worker  */
33*4a64e381SAndroid Build Coastguard Worker 
34*4a64e381SAndroid Build Coastguard Worker #define OTBR_LOG_TAG "WEB"
35*4a64e381SAndroid Build Coastguard Worker 
36*4a64e381SAndroid Build Coastguard Worker #include "web/web-service/wpan_service.hpp"
37*4a64e381SAndroid Build Coastguard Worker 
38*4a64e381SAndroid Build Coastguard Worker #include <sstream>
39*4a64e381SAndroid Build Coastguard Worker 
40*4a64e381SAndroid Build Coastguard Worker #include <inttypes.h>
41*4a64e381SAndroid Build Coastguard Worker #include <stdio.h>
42*4a64e381SAndroid Build Coastguard Worker #include <unistd.h>
43*4a64e381SAndroid Build Coastguard Worker 
44*4a64e381SAndroid Build Coastguard Worker #include "common/byteswap.hpp"
45*4a64e381SAndroid Build Coastguard Worker #include "common/code_utils.hpp"
46*4a64e381SAndroid Build Coastguard Worker 
47*4a64e381SAndroid Build Coastguard Worker namespace otbr {
48*4a64e381SAndroid Build Coastguard Worker namespace Web {
49*4a64e381SAndroid Build Coastguard Worker 
50*4a64e381SAndroid Build Coastguard Worker #define WPAN_RESPONSE_SUCCESS "successful"
51*4a64e381SAndroid Build Coastguard Worker #define WPAN_RESPONSE_FAILURE "failed"
52*4a64e381SAndroid Build Coastguard Worker #define CREDENTIAL_TYPE_NETWORK_KEY "networkKeyType"
53*4a64e381SAndroid Build Coastguard Worker #define CREDENTIAL_TYPE_PSKD "pskdType"
54*4a64e381SAndroid Build Coastguard Worker 
HandleGetQRCodeRequest()55*4a64e381SAndroid Build Coastguard Worker std::string WpanService::HandleGetQRCodeRequest()
56*4a64e381SAndroid Build Coastguard Worker {
57*4a64e381SAndroid Build Coastguard Worker     Json::Value                 root, networkInfo;
58*4a64e381SAndroid Build Coastguard Worker     Json::FastWriter            jsonWriter;
59*4a64e381SAndroid Build Coastguard Worker     std::string                 response;
60*4a64e381SAndroid Build Coastguard Worker     int                         ret = kWpanStatus_Ok;
61*4a64e381SAndroid Build Coastguard Worker     otbr::Web::OpenThreadClient client(mIfName);
62*4a64e381SAndroid Build Coastguard Worker     char                       *rval;
63*4a64e381SAndroid Build Coastguard Worker 
64*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(client.Connect(), ret = kWpanStatus_SetFailed);
65*4a64e381SAndroid Build Coastguard Worker 
66*4a64e381SAndroid Build Coastguard Worker     // eui64 is the only required information to generate the QR code.
67*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit((rval = client.Execute("eui64")) != nullptr, ret = kWpanStatus_GetPropertyFailed);
68*4a64e381SAndroid Build Coastguard Worker 
69*4a64e381SAndroid Build Coastguard Worker exit:
70*4a64e381SAndroid Build Coastguard Worker 
71*4a64e381SAndroid Build Coastguard Worker     root.clear();
72*4a64e381SAndroid Build Coastguard Worker     root["result"] = WPAN_RESPONSE_SUCCESS;
73*4a64e381SAndroid Build Coastguard Worker 
74*4a64e381SAndroid Build Coastguard Worker     if (ret == kWpanStatus_Ok)
75*4a64e381SAndroid Build Coastguard Worker     {
76*4a64e381SAndroid Build Coastguard Worker         root["eui64"] = rval;
77*4a64e381SAndroid Build Coastguard Worker     }
78*4a64e381SAndroid Build Coastguard Worker     else
79*4a64e381SAndroid Build Coastguard Worker     {
80*4a64e381SAndroid Build Coastguard Worker         root["result"] = WPAN_RESPONSE_FAILURE;
81*4a64e381SAndroid Build Coastguard Worker         otbrLogErr("Wpan service error: %d", ret);
82*4a64e381SAndroid Build Coastguard Worker     }
83*4a64e381SAndroid Build Coastguard Worker 
84*4a64e381SAndroid Build Coastguard Worker     response = jsonWriter.write(root);
85*4a64e381SAndroid Build Coastguard Worker     return response;
86*4a64e381SAndroid Build Coastguard Worker }
87*4a64e381SAndroid Build Coastguard Worker 
HandleJoinNetworkRequest(const std::string & aJoinRequest)88*4a64e381SAndroid Build Coastguard Worker std::string WpanService::HandleJoinNetworkRequest(const std::string &aJoinRequest)
89*4a64e381SAndroid Build Coastguard Worker {
90*4a64e381SAndroid Build Coastguard Worker     Json::Value                 root;
91*4a64e381SAndroid Build Coastguard Worker     Json::Reader                reader;
92*4a64e381SAndroid Build Coastguard Worker     Json::FastWriter            jsonWriter;
93*4a64e381SAndroid Build Coastguard Worker     std::string                 response;
94*4a64e381SAndroid Build Coastguard Worker     int                         index;
95*4a64e381SAndroid Build Coastguard Worker     std::string                 credentialType;
96*4a64e381SAndroid Build Coastguard Worker     std::string                 networkKey;
97*4a64e381SAndroid Build Coastguard Worker     std::string                 pskd;
98*4a64e381SAndroid Build Coastguard Worker     std::string                 prefix;
99*4a64e381SAndroid Build Coastguard Worker     bool                        defaultRoute;
100*4a64e381SAndroid Build Coastguard Worker     int                         ret = kWpanStatus_Ok;
101*4a64e381SAndroid Build Coastguard Worker     otbr::Web::OpenThreadClient client(mIfName);
102*4a64e381SAndroid Build Coastguard Worker     char                       *rval;
103*4a64e381SAndroid Build Coastguard Worker 
104*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(client.Connect(), ret = kWpanStatus_SetFailed);
105*4a64e381SAndroid Build Coastguard Worker 
106*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(reader.parse(aJoinRequest.c_str(), root) == true, ret = kWpanStatus_ParseRequestFailed);
107*4a64e381SAndroid Build Coastguard Worker     index          = root["index"].asUInt();
108*4a64e381SAndroid Build Coastguard Worker     credentialType = root["credentialType"].asString();
109*4a64e381SAndroid Build Coastguard Worker     networkKey     = root["networkKey"].asString();
110*4a64e381SAndroid Build Coastguard Worker     pskd           = root["pskd"].asString();
111*4a64e381SAndroid Build Coastguard Worker     prefix         = root["prefix"].asString();
112*4a64e381SAndroid Build Coastguard Worker     defaultRoute   = root["defaultRoute"].asBool();
113*4a64e381SAndroid Build Coastguard Worker 
114*4a64e381SAndroid Build Coastguard Worker     if (prefix.find('/') == std::string::npos)
115*4a64e381SAndroid Build Coastguard Worker     {
116*4a64e381SAndroid Build Coastguard Worker         prefix += "/64";
117*4a64e381SAndroid Build Coastguard Worker     }
118*4a64e381SAndroid Build Coastguard Worker 
119*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(client.FactoryReset(), ret = kWpanStatus_LeaveFailed);
120*4a64e381SAndroid Build Coastguard Worker 
121*4a64e381SAndroid Build Coastguard Worker     if (credentialType == CREDENTIAL_TYPE_NETWORK_KEY)
122*4a64e381SAndroid Build Coastguard Worker     {
123*4a64e381SAndroid Build Coastguard Worker         VerifyOrExit((ret = joinActiveDataset(client, networkKey, mNetworks[index].mChannel,
124*4a64e381SAndroid Build Coastguard Worker                                               mNetworks[index].mPanId)) == kWpanStatus_Ok);
125*4a64e381SAndroid Build Coastguard Worker         VerifyOrExit(client.Execute("ifconfig up") != nullptr, ret = kWpanStatus_JoinFailed);
126*4a64e381SAndroid Build Coastguard Worker     }
127*4a64e381SAndroid Build Coastguard Worker     else if (credentialType == CREDENTIAL_TYPE_PSKD)
128*4a64e381SAndroid Build Coastguard Worker     {
129*4a64e381SAndroid Build Coastguard Worker         VerifyOrExit(client.Execute("ifconfig up") != nullptr, ret = kWpanStatus_JoinFailed);
130*4a64e381SAndroid Build Coastguard Worker         VerifyOrExit(client.Execute("joiner start %s", pskd.c_str()) != nullptr, ret = kWpanStatus_JoinFailed);
131*4a64e381SAndroid Build Coastguard Worker         VerifyOrExit((rval = client.Read("Join ", 5000)) != nullptr, ret = kWpanStatus_JoinFailed);
132*4a64e381SAndroid Build Coastguard Worker         if (strstr(rval, "Join success"))
133*4a64e381SAndroid Build Coastguard Worker         {
134*4a64e381SAndroid Build Coastguard Worker             ExitNow();
135*4a64e381SAndroid Build Coastguard Worker         }
136*4a64e381SAndroid Build Coastguard Worker         else if (strstr(rval, "Join failed [NotFound]"))
137*4a64e381SAndroid Build Coastguard Worker         {
138*4a64e381SAndroid Build Coastguard Worker             ExitNow(ret = kWpanStatus_JoinFailed_NotFound);
139*4a64e381SAndroid Build Coastguard Worker         }
140*4a64e381SAndroid Build Coastguard Worker         else if (strstr(rval, "Join failed [Security]"))
141*4a64e381SAndroid Build Coastguard Worker         {
142*4a64e381SAndroid Build Coastguard Worker             ExitNow(ret = kWpanStatus_JoinFailed_Security);
143*4a64e381SAndroid Build Coastguard Worker         }
144*4a64e381SAndroid Build Coastguard Worker         else
145*4a64e381SAndroid Build Coastguard Worker         {
146*4a64e381SAndroid Build Coastguard Worker             ExitNow(ret = kWpanStatus_JoinFailed);
147*4a64e381SAndroid Build Coastguard Worker         }
148*4a64e381SAndroid Build Coastguard Worker     }
149*4a64e381SAndroid Build Coastguard Worker     else
150*4a64e381SAndroid Build Coastguard Worker     {
151*4a64e381SAndroid Build Coastguard Worker         ExitNow(ret = kWpanStatus_JoinFailed);
152*4a64e381SAndroid Build Coastguard Worker     }
153*4a64e381SAndroid Build Coastguard Worker 
154*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(client.Execute("thread start") != nullptr, ret = kWpanStatus_JoinFailed);
155*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(client.Execute("prefix add %s paso%s", prefix.c_str(), (defaultRoute ? "r" : "")) != nullptr,
156*4a64e381SAndroid Build Coastguard Worker                  ret = kWpanStatus_SetFailed);
157*4a64e381SAndroid Build Coastguard Worker 
158*4a64e381SAndroid Build Coastguard Worker exit:
159*4a64e381SAndroid Build Coastguard Worker 
160*4a64e381SAndroid Build Coastguard Worker     root.clear();
161*4a64e381SAndroid Build Coastguard Worker     root["result"] = WPAN_RESPONSE_SUCCESS;
162*4a64e381SAndroid Build Coastguard Worker 
163*4a64e381SAndroid Build Coastguard Worker     root["error"] = ret;
164*4a64e381SAndroid Build Coastguard Worker     if (ret != kWpanStatus_Ok)
165*4a64e381SAndroid Build Coastguard Worker     {
166*4a64e381SAndroid Build Coastguard Worker         otbrLogErr("Wpan service error: %d", ret);
167*4a64e381SAndroid Build Coastguard Worker         root["result"] = WPAN_RESPONSE_FAILURE;
168*4a64e381SAndroid Build Coastguard Worker     }
169*4a64e381SAndroid Build Coastguard Worker 
170*4a64e381SAndroid Build Coastguard Worker     root["message"] = "";
171*4a64e381SAndroid Build Coastguard Worker     if (ret == kWpanStatus_JoinFailed_NotFound)
172*4a64e381SAndroid Build Coastguard Worker     {
173*4a64e381SAndroid Build Coastguard Worker         root["message"] = "Please make sure this joiner has been added by an active commissioner.";
174*4a64e381SAndroid Build Coastguard Worker     }
175*4a64e381SAndroid Build Coastguard Worker     else if (ret == kWpanStatus_JoinFailed_Security)
176*4a64e381SAndroid Build Coastguard Worker     {
177*4a64e381SAndroid Build Coastguard Worker         root["message"] = "Please make sure the provided PSKd matches the one given to the commissioner.";
178*4a64e381SAndroid Build Coastguard Worker     }
179*4a64e381SAndroid Build Coastguard Worker 
180*4a64e381SAndroid Build Coastguard Worker     response = jsonWriter.write(root);
181*4a64e381SAndroid Build Coastguard Worker     return response;
182*4a64e381SAndroid Build Coastguard Worker }
183*4a64e381SAndroid Build Coastguard Worker 
HandleFormNetworkRequest(const std::string & aFormRequest)184*4a64e381SAndroid Build Coastguard Worker std::string WpanService::HandleFormNetworkRequest(const std::string &aFormRequest)
185*4a64e381SAndroid Build Coastguard Worker {
186*4a64e381SAndroid Build Coastguard Worker     Json::Value                 root;
187*4a64e381SAndroid Build Coastguard Worker     Json::FastWriter            jsonWriter;
188*4a64e381SAndroid Build Coastguard Worker     Json::Reader                reader;
189*4a64e381SAndroid Build Coastguard Worker     std::string                 response;
190*4a64e381SAndroid Build Coastguard Worker     otbr::Psk::Pskc             psk;
191*4a64e381SAndroid Build Coastguard Worker     char                        pskcStr[OT_PSKC_MAX_LENGTH * 2 + 1];
192*4a64e381SAndroid Build Coastguard Worker     uint8_t                     extPanIdBytes[OT_EXTENDED_PANID_LENGTH];
193*4a64e381SAndroid Build Coastguard Worker     std::string                 networkKey;
194*4a64e381SAndroid Build Coastguard Worker     std::string                 prefix;
195*4a64e381SAndroid Build Coastguard Worker     uint16_t                    channel;
196*4a64e381SAndroid Build Coastguard Worker     std::string                 networkName;
197*4a64e381SAndroid Build Coastguard Worker     std::string                 passphrase;
198*4a64e381SAndroid Build Coastguard Worker     uint16_t                    panId;
199*4a64e381SAndroid Build Coastguard Worker     uint64_t                    extPanId;
200*4a64e381SAndroid Build Coastguard Worker     bool                        defaultRoute;
201*4a64e381SAndroid Build Coastguard Worker     int                         ret = kWpanStatus_Ok;
202*4a64e381SAndroid Build Coastguard Worker     otbr::Web::OpenThreadClient client(mIfName);
203*4a64e381SAndroid Build Coastguard Worker 
204*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(client.Connect(), ret = kWpanStatus_SetFailed);
205*4a64e381SAndroid Build Coastguard Worker 
206*4a64e381SAndroid Build Coastguard Worker     pskcStr[OT_PSKC_MAX_LENGTH * 2] = '\0'; // for manipulating with strlen
207*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(reader.parse(aFormRequest.c_str(), root) == true, ret = kWpanStatus_ParseRequestFailed);
208*4a64e381SAndroid Build Coastguard Worker     networkKey  = root["networkKey"].asString();
209*4a64e381SAndroid Build Coastguard Worker     prefix      = root["prefix"].asString();
210*4a64e381SAndroid Build Coastguard Worker     channel     = root["channel"].asUInt();
211*4a64e381SAndroid Build Coastguard Worker     networkName = root["networkName"].asString();
212*4a64e381SAndroid Build Coastguard Worker     passphrase  = root["passphrase"].asString();
213*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(sscanf(root["panId"].asString().c_str(), "%hx", &panId) == 1, ret = kWpanStatus_ParseRequestFailed);
214*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(sscanf(root["extPanId"].asString().c_str(), "%" PRIx64, &extPanId) == 1,
215*4a64e381SAndroid Build Coastguard Worker                  ret = kWpanStatus_ParseRequestFailed);
216*4a64e381SAndroid Build Coastguard Worker     defaultRoute = root["defaultRoute"].asBool();
217*4a64e381SAndroid Build Coastguard Worker 
218*4a64e381SAndroid Build Coastguard Worker     otbr::Utils::Hex2Bytes(root["extPanId"].asString().c_str(), extPanIdBytes, OT_EXTENDED_PANID_LENGTH);
219*4a64e381SAndroid Build Coastguard Worker     otbr::Utils::Bytes2Hex(psk.ComputePskc(extPanIdBytes, networkName.c_str(), passphrase.c_str()), OT_PSKC_MAX_LENGTH,
220*4a64e381SAndroid Build Coastguard Worker                            pskcStr);
221*4a64e381SAndroid Build Coastguard Worker 
222*4a64e381SAndroid Build Coastguard Worker     if (prefix.find('/') == std::string::npos)
223*4a64e381SAndroid Build Coastguard Worker     {
224*4a64e381SAndroid Build Coastguard Worker         prefix += "/64";
225*4a64e381SAndroid Build Coastguard Worker     }
226*4a64e381SAndroid Build Coastguard Worker 
227*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(client.FactoryReset(), ret = kWpanStatus_LeaveFailed);
228*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit((ret = formActiveDataset(client, networkKey, networkName, pskcStr, channel, extPanId, panId)) ==
229*4a64e381SAndroid Build Coastguard Worker                  kWpanStatus_Ok);
230*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(client.Execute("ifconfig up") != nullptr, ret = kWpanStatus_FormFailed);
231*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(client.Execute("thread start") != nullptr, ret = kWpanStatus_FormFailed);
232*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(client.Execute("prefix add %s paso%s", prefix.c_str(), (defaultRoute ? "r" : "")) != nullptr,
233*4a64e381SAndroid Build Coastguard Worker                  ret = kWpanStatus_SetFailed);
234*4a64e381SAndroid Build Coastguard Worker exit:
235*4a64e381SAndroid Build Coastguard Worker 
236*4a64e381SAndroid Build Coastguard Worker     root.clear();
237*4a64e381SAndroid Build Coastguard Worker 
238*4a64e381SAndroid Build Coastguard Worker     root["result"] = WPAN_RESPONSE_SUCCESS;
239*4a64e381SAndroid Build Coastguard Worker     root["error"]  = ret;
240*4a64e381SAndroid Build Coastguard Worker     if (ret != kWpanStatus_Ok)
241*4a64e381SAndroid Build Coastguard Worker     {
242*4a64e381SAndroid Build Coastguard Worker         otbrLogErr("Wpan service error: %d", ret);
243*4a64e381SAndroid Build Coastguard Worker         root["result"] = WPAN_RESPONSE_FAILURE;
244*4a64e381SAndroid Build Coastguard Worker     }
245*4a64e381SAndroid Build Coastguard Worker     response = jsonWriter.write(root);
246*4a64e381SAndroid Build Coastguard Worker     return response;
247*4a64e381SAndroid Build Coastguard Worker }
248*4a64e381SAndroid Build Coastguard Worker 
HandleAddPrefixRequest(const std::string & aAddPrefixRequest)249*4a64e381SAndroid Build Coastguard Worker std::string WpanService::HandleAddPrefixRequest(const std::string &aAddPrefixRequest)
250*4a64e381SAndroid Build Coastguard Worker {
251*4a64e381SAndroid Build Coastguard Worker     Json::Value                 root;
252*4a64e381SAndroid Build Coastguard Worker     Json::FastWriter            jsonWriter;
253*4a64e381SAndroid Build Coastguard Worker     Json::Reader                reader;
254*4a64e381SAndroid Build Coastguard Worker     std::string                 response;
255*4a64e381SAndroid Build Coastguard Worker     std::string                 prefix;
256*4a64e381SAndroid Build Coastguard Worker     bool                        defaultRoute;
257*4a64e381SAndroid Build Coastguard Worker     int                         ret = kWpanStatus_Ok;
258*4a64e381SAndroid Build Coastguard Worker     otbr::Web::OpenThreadClient client(mIfName);
259*4a64e381SAndroid Build Coastguard Worker 
260*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(client.Connect(), ret = kWpanStatus_SetFailed);
261*4a64e381SAndroid Build Coastguard Worker 
262*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(reader.parse(aAddPrefixRequest.c_str(), root) == true, ret = kWpanStatus_ParseRequestFailed);
263*4a64e381SAndroid Build Coastguard Worker     prefix       = root["prefix"].asString();
264*4a64e381SAndroid Build Coastguard Worker     defaultRoute = root["defaultRoute"].asBool();
265*4a64e381SAndroid Build Coastguard Worker 
266*4a64e381SAndroid Build Coastguard Worker     if (prefix.find('/') == std::string::npos)
267*4a64e381SAndroid Build Coastguard Worker     {
268*4a64e381SAndroid Build Coastguard Worker         prefix += "/64";
269*4a64e381SAndroid Build Coastguard Worker     }
270*4a64e381SAndroid Build Coastguard Worker 
271*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(client.Execute("prefix add %s paso%s", prefix.c_str(), (defaultRoute ? "r" : "")) != nullptr,
272*4a64e381SAndroid Build Coastguard Worker                  ret = kWpanStatus_SetGatewayFailed);
273*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(client.Execute("netdata register") != nullptr, ret = kWpanStatus_SetGatewayFailed);
274*4a64e381SAndroid Build Coastguard Worker exit:
275*4a64e381SAndroid Build Coastguard Worker 
276*4a64e381SAndroid Build Coastguard Worker     root.clear();
277*4a64e381SAndroid Build Coastguard Worker 
278*4a64e381SAndroid Build Coastguard Worker     root["result"] = WPAN_RESPONSE_SUCCESS;
279*4a64e381SAndroid Build Coastguard Worker     root["error"]  = ret;
280*4a64e381SAndroid Build Coastguard Worker     if (ret != kWpanStatus_Ok)
281*4a64e381SAndroid Build Coastguard Worker     {
282*4a64e381SAndroid Build Coastguard Worker         otbrLogErr("Wpan service error: %d", ret);
283*4a64e381SAndroid Build Coastguard Worker         root["result"] = WPAN_RESPONSE_FAILURE;
284*4a64e381SAndroid Build Coastguard Worker     }
285*4a64e381SAndroid Build Coastguard Worker     response = jsonWriter.write(root);
286*4a64e381SAndroid Build Coastguard Worker     return response;
287*4a64e381SAndroid Build Coastguard Worker }
288*4a64e381SAndroid Build Coastguard Worker 
HandleDeletePrefixRequest(const std::string & aDeleteRequest)289*4a64e381SAndroid Build Coastguard Worker std::string WpanService::HandleDeletePrefixRequest(const std::string &aDeleteRequest)
290*4a64e381SAndroid Build Coastguard Worker {
291*4a64e381SAndroid Build Coastguard Worker     Json::Value                 root;
292*4a64e381SAndroid Build Coastguard Worker     Json::FastWriter            jsonWriter;
293*4a64e381SAndroid Build Coastguard Worker     Json::Reader                reader;
294*4a64e381SAndroid Build Coastguard Worker     std::string                 response;
295*4a64e381SAndroid Build Coastguard Worker     std::string                 prefix;
296*4a64e381SAndroid Build Coastguard Worker     int                         ret = kWpanStatus_Ok;
297*4a64e381SAndroid Build Coastguard Worker     otbr::Web::OpenThreadClient client(mIfName);
298*4a64e381SAndroid Build Coastguard Worker 
299*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(client.Connect(), ret = kWpanStatus_SetFailed);
300*4a64e381SAndroid Build Coastguard Worker 
301*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(reader.parse(aDeleteRequest.c_str(), root) == true, ret = kWpanStatus_ParseRequestFailed);
302*4a64e381SAndroid Build Coastguard Worker     prefix = root["prefix"].asString();
303*4a64e381SAndroid Build Coastguard Worker 
304*4a64e381SAndroid Build Coastguard Worker     if (prefix.find('/') == std::string::npos)
305*4a64e381SAndroid Build Coastguard Worker     {
306*4a64e381SAndroid Build Coastguard Worker         prefix += "/64";
307*4a64e381SAndroid Build Coastguard Worker     }
308*4a64e381SAndroid Build Coastguard Worker 
309*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(client.Execute("prefix remove %s", prefix.c_str()) != nullptr, ret = kWpanStatus_SetGatewayFailed);
310*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(client.Execute("netdata register") != nullptr, ret = kWpanStatus_SetGatewayFailed);
311*4a64e381SAndroid Build Coastguard Worker exit:
312*4a64e381SAndroid Build Coastguard Worker 
313*4a64e381SAndroid Build Coastguard Worker     root.clear();
314*4a64e381SAndroid Build Coastguard Worker     root["result"] = WPAN_RESPONSE_SUCCESS;
315*4a64e381SAndroid Build Coastguard Worker 
316*4a64e381SAndroid Build Coastguard Worker     root["error"] = ret;
317*4a64e381SAndroid Build Coastguard Worker     if (ret != kWpanStatus_Ok)
318*4a64e381SAndroid Build Coastguard Worker     {
319*4a64e381SAndroid Build Coastguard Worker         otbrLogErr("Wpan service error: %d", ret);
320*4a64e381SAndroid Build Coastguard Worker         root["result"] = WPAN_RESPONSE_FAILURE;
321*4a64e381SAndroid Build Coastguard Worker     }
322*4a64e381SAndroid Build Coastguard Worker     response = jsonWriter.write(root);
323*4a64e381SAndroid Build Coastguard Worker     return response;
324*4a64e381SAndroid Build Coastguard Worker }
325*4a64e381SAndroid Build Coastguard Worker 
HandleStatusRequest()326*4a64e381SAndroid Build Coastguard Worker std::string WpanService::HandleStatusRequest()
327*4a64e381SAndroid Build Coastguard Worker {
328*4a64e381SAndroid Build Coastguard Worker     Json::Value                 root, networkInfo;
329*4a64e381SAndroid Build Coastguard Worker     Json::FastWriter            jsonWriter;
330*4a64e381SAndroid Build Coastguard Worker     std::string                 response, networkName, extPanId, propertyValue;
331*4a64e381SAndroid Build Coastguard Worker     int                         ret = kWpanStatus_Ok;
332*4a64e381SAndroid Build Coastguard Worker     otbr::Web::OpenThreadClient client(mIfName);
333*4a64e381SAndroid Build Coastguard Worker     char                       *rval;
334*4a64e381SAndroid Build Coastguard Worker 
335*4a64e381SAndroid Build Coastguard Worker     networkInfo["WPAN service"] = "uninitialized";
336*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(client.Connect(), ret = kWpanStatus_SetFailed);
337*4a64e381SAndroid Build Coastguard Worker 
338*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit((rval = client.Execute("state")) != nullptr, ret = kWpanStatus_GetPropertyFailed);
339*4a64e381SAndroid Build Coastguard Worker     networkInfo["RCP:State"] = rval;
340*4a64e381SAndroid Build Coastguard Worker 
341*4a64e381SAndroid Build Coastguard Worker     if (!strcmp(rval, "disabled"))
342*4a64e381SAndroid Build Coastguard Worker     {
343*4a64e381SAndroid Build Coastguard Worker         networkInfo["WPAN service"] = "offline";
344*4a64e381SAndroid Build Coastguard Worker         ExitNow();
345*4a64e381SAndroid Build Coastguard Worker     }
346*4a64e381SAndroid Build Coastguard Worker     else if (!strcmp(rval, "detached"))
347*4a64e381SAndroid Build Coastguard Worker     {
348*4a64e381SAndroid Build Coastguard Worker         networkInfo["WPAN service"] = "associating";
349*4a64e381SAndroid Build Coastguard Worker         ExitNow();
350*4a64e381SAndroid Build Coastguard Worker     }
351*4a64e381SAndroid Build Coastguard Worker     else
352*4a64e381SAndroid Build Coastguard Worker     {
353*4a64e381SAndroid Build Coastguard Worker         networkInfo["WPAN service"] = "associated";
354*4a64e381SAndroid Build Coastguard Worker     }
355*4a64e381SAndroid Build Coastguard Worker 
356*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit((rval = client.Execute("version")) != nullptr, ret = kWpanStatus_GetPropertyFailed);
357*4a64e381SAndroid Build Coastguard Worker     networkInfo["OpenThread:Version"] = rval;
358*4a64e381SAndroid Build Coastguard Worker 
359*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit((rval = client.Execute("version api")) != nullptr, ret = kWpanStatus_GetPropertyFailed);
360*4a64e381SAndroid Build Coastguard Worker     networkInfo["OpenThread:Version API"] = rval;
361*4a64e381SAndroid Build Coastguard Worker 
362*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit((rval = client.Execute("rcp version")) != nullptr, ret = kWpanStatus_GetPropertyFailed);
363*4a64e381SAndroid Build Coastguard Worker     networkInfo["RCP:Version"] = rval;
364*4a64e381SAndroid Build Coastguard Worker 
365*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit((rval = client.Execute("eui64")) != nullptr, ret = kWpanStatus_GetPropertyFailed);
366*4a64e381SAndroid Build Coastguard Worker     networkInfo["RCP:EUI64"] = rval;
367*4a64e381SAndroid Build Coastguard Worker 
368*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit((rval = client.Execute("channel")) != nullptr, ret = kWpanStatus_GetPropertyFailed);
369*4a64e381SAndroid Build Coastguard Worker     networkInfo["RCP:Channel"] = rval;
370*4a64e381SAndroid Build Coastguard Worker 
371*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit((rval = client.Execute("txpower")) != nullptr, ret = kWpanStatus_GetPropertyFailed);
372*4a64e381SAndroid Build Coastguard Worker     networkInfo["RCP:TxPower"] = rval;
373*4a64e381SAndroid Build Coastguard Worker 
374*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit((rval = client.Execute("networkname")) != nullptr, ret = kWpanStatus_GetPropertyFailed);
375*4a64e381SAndroid Build Coastguard Worker     networkInfo["Network:Name"] = rval;
376*4a64e381SAndroid Build Coastguard Worker 
377*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit((rval = client.Execute("extpanid")) != nullptr, ret = kWpanStatus_GetPropertyFailed);
378*4a64e381SAndroid Build Coastguard Worker     networkInfo["Network:XPANID"] = rval;
379*4a64e381SAndroid Build Coastguard Worker 
380*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit((rval = client.Execute("panid")) != nullptr, ret = kWpanStatus_GetPropertyFailed);
381*4a64e381SAndroid Build Coastguard Worker     networkInfo["Network:PANID"] = rval;
382*4a64e381SAndroid Build Coastguard Worker 
383*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit((rval = client.Execute("partitionid")) != nullptr, ret = kWpanStatus_GetPropertyFailed);
384*4a64e381SAndroid Build Coastguard Worker     networkInfo["Network:PartitionID"] = rval;
385*4a64e381SAndroid Build Coastguard Worker 
386*4a64e381SAndroid Build Coastguard Worker     {
387*4a64e381SAndroid Build Coastguard Worker         static const char kMeshLocalPrefixLocator[]       = "Mesh Local Prefix: ";
388*4a64e381SAndroid Build Coastguard Worker         static const char kMeshLocalAddressTokenLocator[] = "0:ff:fe00:";
389*4a64e381SAndroid Build Coastguard Worker         static const char localAddressToken[]             = "fd";
390*4a64e381SAndroid Build Coastguard Worker         static const char linkLocalAddressToken[]         = "fe80";
391*4a64e381SAndroid Build Coastguard Worker         std::string       meshLocalPrefix                 = "";
392*4a64e381SAndroid Build Coastguard Worker 
393*4a64e381SAndroid Build Coastguard Worker         VerifyOrExit((rval = client.Execute("dataset active")) != nullptr, ret = kWpanStatus_GetPropertyFailed);
394*4a64e381SAndroid Build Coastguard Worker         rval = strstr(rval, kMeshLocalPrefixLocator);
395*4a64e381SAndroid Build Coastguard Worker         if (rval != nullptr)
396*4a64e381SAndroid Build Coastguard Worker         {
397*4a64e381SAndroid Build Coastguard Worker             rval += sizeof(kMeshLocalPrefixLocator) - 1;
398*4a64e381SAndroid Build Coastguard Worker             *strstr(rval, "\r\n")               = '\0';
399*4a64e381SAndroid Build Coastguard Worker             networkInfo["IPv6:MeshLocalPrefix"] = rval;
400*4a64e381SAndroid Build Coastguard Worker 
401*4a64e381SAndroid Build Coastguard Worker             meshLocalPrefix = rval;
402*4a64e381SAndroid Build Coastguard Worker             meshLocalPrefix.resize(meshLocalPrefix.find(":/"));
403*4a64e381SAndroid Build Coastguard Worker         }
404*4a64e381SAndroid Build Coastguard Worker 
405*4a64e381SAndroid Build Coastguard Worker         VerifyOrExit((rval = client.Execute("ipaddr")) != nullptr, ret = kWpanStatus_GetPropertyFailed);
406*4a64e381SAndroid Build Coastguard Worker 
407*4a64e381SAndroid Build Coastguard Worker         for (rval = strtok(rval, "\r\n"); rval != nullptr; rval = strtok(nullptr, "\r\n"))
408*4a64e381SAndroid Build Coastguard Worker         {
409*4a64e381SAndroid Build Coastguard Worker             char *meshLocalAddressToken = nullptr;
410*4a64e381SAndroid Build Coastguard Worker 
411*4a64e381SAndroid Build Coastguard Worker             if (strstr(rval, "> ") != nullptr)
412*4a64e381SAndroid Build Coastguard Worker             {
413*4a64e381SAndroid Build Coastguard Worker                 rval += 2;
414*4a64e381SAndroid Build Coastguard Worker             }
415*4a64e381SAndroid Build Coastguard Worker 
416*4a64e381SAndroid Build Coastguard Worker             if (strstr(rval, linkLocalAddressToken) == rval)
417*4a64e381SAndroid Build Coastguard Worker             {
418*4a64e381SAndroid Build Coastguard Worker                 networkInfo["IPv6:LinkLocalAddress"] = rval;
419*4a64e381SAndroid Build Coastguard Worker                 continue;
420*4a64e381SAndroid Build Coastguard Worker             }
421*4a64e381SAndroid Build Coastguard Worker 
422*4a64e381SAndroid Build Coastguard Worker             meshLocalAddressToken = strstr(rval, kMeshLocalAddressTokenLocator);
423*4a64e381SAndroid Build Coastguard Worker 
424*4a64e381SAndroid Build Coastguard Worker             if (meshLocalAddressToken == nullptr)
425*4a64e381SAndroid Build Coastguard Worker             {
426*4a64e381SAndroid Build Coastguard Worker                 if ((meshLocalPrefix.size() > 0) && (strstr(rval, meshLocalPrefix.c_str()) == rval))
427*4a64e381SAndroid Build Coastguard Worker                 {
428*4a64e381SAndroid Build Coastguard Worker                     networkInfo["IPv6:MeshLocalAddress"] = rval;
429*4a64e381SAndroid Build Coastguard Worker                     continue;
430*4a64e381SAndroid Build Coastguard Worker                 }
431*4a64e381SAndroid Build Coastguard Worker 
432*4a64e381SAndroid Build Coastguard Worker                 if (strstr(rval, localAddressToken) != rval)
433*4a64e381SAndroid Build Coastguard Worker                 {
434*4a64e381SAndroid Build Coastguard Worker                     networkInfo["IPv6:GlobalAddress"] = rval;
435*4a64e381SAndroid Build Coastguard Worker                 }
436*4a64e381SAndroid Build Coastguard Worker                 else
437*4a64e381SAndroid Build Coastguard Worker                 {
438*4a64e381SAndroid Build Coastguard Worker                     networkInfo["IPv6:LocalAddress"] = rval;
439*4a64e381SAndroid Build Coastguard Worker                 }
440*4a64e381SAndroid Build Coastguard Worker             }
441*4a64e381SAndroid Build Coastguard Worker             else
442*4a64e381SAndroid Build Coastguard Worker             {
443*4a64e381SAndroid Build Coastguard Worker                 *meshLocalAddressToken              = '\0';
444*4a64e381SAndroid Build Coastguard Worker                 meshLocalPrefix                     = rval;
445*4a64e381SAndroid Build Coastguard Worker                 networkInfo["IPv6:MeshLocalPrefix"] = rval;
446*4a64e381SAndroid Build Coastguard Worker                 std::string la                      = networkInfo.get("IPv6:LocalAddress", "unknown").asString();
447*4a64e381SAndroid Build Coastguard Worker                 if (strstr(rval, la.c_str()) != nullptr)
448*4a64e381SAndroid Build Coastguard Worker                 {
449*4a64e381SAndroid Build Coastguard Worker                     networkInfo["IPv6:MeshLocalAddress"] = networkInfo.get("IPv6:LocalAddress", "notfound").asString();
450*4a64e381SAndroid Build Coastguard Worker                     networkInfo.removeMember("IPv6:LocalAddress");
451*4a64e381SAndroid Build Coastguard Worker                 }
452*4a64e381SAndroid Build Coastguard Worker             }
453*4a64e381SAndroid Build Coastguard Worker         }
454*4a64e381SAndroid Build Coastguard Worker     }
455*4a64e381SAndroid Build Coastguard Worker 
456*4a64e381SAndroid Build Coastguard Worker exit:
457*4a64e381SAndroid Build Coastguard Worker     root["result"] = networkInfo;
458*4a64e381SAndroid Build Coastguard Worker 
459*4a64e381SAndroid Build Coastguard Worker     if (ret != kWpanStatus_Ok)
460*4a64e381SAndroid Build Coastguard Worker     {
461*4a64e381SAndroid Build Coastguard Worker         root["result"] = WPAN_RESPONSE_FAILURE;
462*4a64e381SAndroid Build Coastguard Worker         otbrLogErr("Wpan service error: %d", ret);
463*4a64e381SAndroid Build Coastguard Worker     }
464*4a64e381SAndroid Build Coastguard Worker     root["error"] = ret;
465*4a64e381SAndroid Build Coastguard Worker     response      = jsonWriter.write(root);
466*4a64e381SAndroid Build Coastguard Worker     return response;
467*4a64e381SAndroid Build Coastguard Worker }
468*4a64e381SAndroid Build Coastguard Worker 
HandleAvailableNetworkRequest()469*4a64e381SAndroid Build Coastguard Worker std::string WpanService::HandleAvailableNetworkRequest()
470*4a64e381SAndroid Build Coastguard Worker {
471*4a64e381SAndroid Build Coastguard Worker     Json::Value                 root, networks, networkInfo;
472*4a64e381SAndroid Build Coastguard Worker     Json::FastWriter            jsonWriter;
473*4a64e381SAndroid Build Coastguard Worker     std::string                 response;
474*4a64e381SAndroid Build Coastguard Worker     int                         ret = kWpanStatus_Ok;
475*4a64e381SAndroid Build Coastguard Worker     otbr::Web::OpenThreadClient client(mIfName);
476*4a64e381SAndroid Build Coastguard Worker 
477*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(client.Connect(), ret = kWpanStatus_ScanFailed);
478*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit((mNetworksCount = client.Scan(mNetworks, sizeof(mNetworks) / sizeof(mNetworks[0]))) > 0,
479*4a64e381SAndroid Build Coastguard Worker                  ret = kWpanStatus_NetworkNotFound);
480*4a64e381SAndroid Build Coastguard Worker 
481*4a64e381SAndroid Build Coastguard Worker     for (int i = 0; i < mNetworksCount; i++)
482*4a64e381SAndroid Build Coastguard Worker     {
483*4a64e381SAndroid Build Coastguard Worker         char panId[OT_PANID_LENGTH * 2 + 3], hardwareAddress[OT_HARDWARE_ADDRESS_LENGTH * 2 + 1];
484*4a64e381SAndroid Build Coastguard Worker         otbr::Utils::Bytes2Hex(mNetworks[i].mHardwareAddress, OT_HARDWARE_ADDRESS_LENGTH, hardwareAddress);
485*4a64e381SAndroid Build Coastguard Worker         snprintf(panId, sizeof(panId), "0x%X", mNetworks[i].mPanId);
486*4a64e381SAndroid Build Coastguard Worker         networkInfo[i]["pi"] = panId;
487*4a64e381SAndroid Build Coastguard Worker         networkInfo[i]["ch"] = mNetworks[i].mChannel;
488*4a64e381SAndroid Build Coastguard Worker         networkInfo[i]["ha"] = hardwareAddress;
489*4a64e381SAndroid Build Coastguard Worker     }
490*4a64e381SAndroid Build Coastguard Worker 
491*4a64e381SAndroid Build Coastguard Worker     root["result"] = networkInfo;
492*4a64e381SAndroid Build Coastguard Worker 
493*4a64e381SAndroid Build Coastguard Worker exit:
494*4a64e381SAndroid Build Coastguard Worker     if (ret != kWpanStatus_Ok)
495*4a64e381SAndroid Build Coastguard Worker     {
496*4a64e381SAndroid Build Coastguard Worker         root["result"] = WPAN_RESPONSE_FAILURE;
497*4a64e381SAndroid Build Coastguard Worker         otbrLogErr("Error is %d", ret);
498*4a64e381SAndroid Build Coastguard Worker     }
499*4a64e381SAndroid Build Coastguard Worker     root["error"] = ret;
500*4a64e381SAndroid Build Coastguard Worker     response      = jsonWriter.write(root);
501*4a64e381SAndroid Build Coastguard Worker     return response;
502*4a64e381SAndroid Build Coastguard Worker }
503*4a64e381SAndroid Build Coastguard Worker 
GetWpanServiceStatus(std::string & aNetworkName,std::string & aExtPanId) const504*4a64e381SAndroid Build Coastguard Worker int WpanService::GetWpanServiceStatus(std::string &aNetworkName, std::string &aExtPanId) const
505*4a64e381SAndroid Build Coastguard Worker {
506*4a64e381SAndroid Build Coastguard Worker     int                         status = kWpanStatus_Ok;
507*4a64e381SAndroid Build Coastguard Worker     otbr::Web::OpenThreadClient client(mIfName);
508*4a64e381SAndroid Build Coastguard Worker     const char                 *rval;
509*4a64e381SAndroid Build Coastguard Worker 
510*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(client.Connect(), status = kWpanStatus_Uninitialized);
511*4a64e381SAndroid Build Coastguard Worker     rval = client.Execute("state");
512*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(rval != nullptr, status = kWpanStatus_Down);
513*4a64e381SAndroid Build Coastguard Worker     if (!strcmp(rval, "disabled"))
514*4a64e381SAndroid Build Coastguard Worker     {
515*4a64e381SAndroid Build Coastguard Worker         status = kWpanStatus_Offline;
516*4a64e381SAndroid Build Coastguard Worker     }
517*4a64e381SAndroid Build Coastguard Worker     else if (!strcmp(rval, "detached"))
518*4a64e381SAndroid Build Coastguard Worker     {
519*4a64e381SAndroid Build Coastguard Worker         status = kWpanStatus_Associating;
520*4a64e381SAndroid Build Coastguard Worker     }
521*4a64e381SAndroid Build Coastguard Worker     else
522*4a64e381SAndroid Build Coastguard Worker     {
523*4a64e381SAndroid Build Coastguard Worker         rval = client.Execute("networkname");
524*4a64e381SAndroid Build Coastguard Worker         VerifyOrExit(rval != nullptr, status = kWpanStatus_Down);
525*4a64e381SAndroid Build Coastguard Worker         aNetworkName = rval;
526*4a64e381SAndroid Build Coastguard Worker 
527*4a64e381SAndroid Build Coastguard Worker         rval = client.Execute("extpanid");
528*4a64e381SAndroid Build Coastguard Worker         VerifyOrExit(rval != nullptr, status = kWpanStatus_Down);
529*4a64e381SAndroid Build Coastguard Worker         aExtPanId = rval;
530*4a64e381SAndroid Build Coastguard Worker     }
531*4a64e381SAndroid Build Coastguard Worker 
532*4a64e381SAndroid Build Coastguard Worker exit:
533*4a64e381SAndroid Build Coastguard Worker 
534*4a64e381SAndroid Build Coastguard Worker     return status;
535*4a64e381SAndroid Build Coastguard Worker }
536*4a64e381SAndroid Build Coastguard Worker 
HandleCommission(const std::string & aCommissionRequest)537*4a64e381SAndroid Build Coastguard Worker std::string WpanService::HandleCommission(const std::string &aCommissionRequest)
538*4a64e381SAndroid Build Coastguard Worker {
539*4a64e381SAndroid Build Coastguard Worker     Json::Value      root;
540*4a64e381SAndroid Build Coastguard Worker     Json::Reader     reader;
541*4a64e381SAndroid Build Coastguard Worker     Json::FastWriter jsonWriter;
542*4a64e381SAndroid Build Coastguard Worker     int              ret = kWpanStatus_Ok;
543*4a64e381SAndroid Build Coastguard Worker     std::string      pskd;
544*4a64e381SAndroid Build Coastguard Worker     std::string      response;
545*4a64e381SAndroid Build Coastguard Worker     const char      *rval;
546*4a64e381SAndroid Build Coastguard Worker 
547*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(reader.parse(aCommissionRequest.c_str(), root) == true, ret = kWpanStatus_ParseRequestFailed);
548*4a64e381SAndroid Build Coastguard Worker     pskd = root["pskd"].asString();
549*4a64e381SAndroid Build Coastguard Worker 
550*4a64e381SAndroid Build Coastguard Worker     {
551*4a64e381SAndroid Build Coastguard Worker         otbr::Web::OpenThreadClient client(mIfName);
552*4a64e381SAndroid Build Coastguard Worker 
553*4a64e381SAndroid Build Coastguard Worker         VerifyOrExit(client.Connect(), ret = kWpanStatus_Uninitialized);
554*4a64e381SAndroid Build Coastguard Worker 
555*4a64e381SAndroid Build Coastguard Worker         for (int i = 0; i < 5; i++)
556*4a64e381SAndroid Build Coastguard Worker         {
557*4a64e381SAndroid Build Coastguard Worker             VerifyOrExit((rval = client.Execute("commissioner state")) != nullptr, ret = kWpanStatus_Down);
558*4a64e381SAndroid Build Coastguard Worker 
559*4a64e381SAndroid Build Coastguard Worker             if (strcmp(rval, "disabled") == 0)
560*4a64e381SAndroid Build Coastguard Worker             {
561*4a64e381SAndroid Build Coastguard Worker                 VerifyOrExit((rval = client.Execute("commissioner start")) != nullptr, ret = kWpanStatus_Down);
562*4a64e381SAndroid Build Coastguard Worker             }
563*4a64e381SAndroid Build Coastguard Worker             else if (strcmp(rval, "active") == 0)
564*4a64e381SAndroid Build Coastguard Worker             {
565*4a64e381SAndroid Build Coastguard Worker                 VerifyOrExit(client.Execute("commissioner joiner add * %s", pskd.c_str()) != nullptr,
566*4a64e381SAndroid Build Coastguard Worker                              ret = kWpanStatus_Down);
567*4a64e381SAndroid Build Coastguard Worker                 root["error"] = ret;
568*4a64e381SAndroid Build Coastguard Worker                 ExitNow();
569*4a64e381SAndroid Build Coastguard Worker             }
570*4a64e381SAndroid Build Coastguard Worker 
571*4a64e381SAndroid Build Coastguard Worker             sleep(1);
572*4a64e381SAndroid Build Coastguard Worker         }
573*4a64e381SAndroid Build Coastguard Worker 
574*4a64e381SAndroid Build Coastguard Worker         client.Execute("commissioner stop");
575*4a64e381SAndroid Build Coastguard Worker     }
576*4a64e381SAndroid Build Coastguard Worker 
577*4a64e381SAndroid Build Coastguard Worker     ret = kWpanStatus_SetFailed;
578*4a64e381SAndroid Build Coastguard Worker 
579*4a64e381SAndroid Build Coastguard Worker exit:
580*4a64e381SAndroid Build Coastguard Worker 
581*4a64e381SAndroid Build Coastguard Worker     root.clear();
582*4a64e381SAndroid Build Coastguard Worker     root["result"] = WPAN_RESPONSE_SUCCESS;
583*4a64e381SAndroid Build Coastguard Worker     root["error"]  = ret;
584*4a64e381SAndroid Build Coastguard Worker 
585*4a64e381SAndroid Build Coastguard Worker     if (ret != kWpanStatus_Ok)
586*4a64e381SAndroid Build Coastguard Worker     {
587*4a64e381SAndroid Build Coastguard Worker         root["result"] = WPAN_RESPONSE_FAILURE;
588*4a64e381SAndroid Build Coastguard Worker         otbrLogErr("error: %d", ret);
589*4a64e381SAndroid Build Coastguard Worker     }
590*4a64e381SAndroid Build Coastguard Worker     response = jsonWriter.write(root);
591*4a64e381SAndroid Build Coastguard Worker 
592*4a64e381SAndroid Build Coastguard Worker     return response;
593*4a64e381SAndroid Build Coastguard Worker }
594*4a64e381SAndroid Build Coastguard Worker 
joinActiveDataset(otbr::Web::OpenThreadClient & aClient,const std::string & aNetworkKey,uint16_t aChannel,uint16_t aPanId)595*4a64e381SAndroid Build Coastguard Worker int WpanService::joinActiveDataset(otbr::Web::OpenThreadClient &aClient,
596*4a64e381SAndroid Build Coastguard Worker                                    const std::string           &aNetworkKey,
597*4a64e381SAndroid Build Coastguard Worker                                    uint16_t                     aChannel,
598*4a64e381SAndroid Build Coastguard Worker                                    uint16_t                     aPanId)
599*4a64e381SAndroid Build Coastguard Worker {
600*4a64e381SAndroid Build Coastguard Worker     int ret = kWpanStatus_Ok;
601*4a64e381SAndroid Build Coastguard Worker 
602*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(aClient.Execute("dataset clear") != nullptr, ret = kWpanStatus_SetFailed);
603*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(aClient.Execute("dataset networkkey %s", aNetworkKey.c_str()) != nullptr, ret = kWpanStatus_SetFailed);
604*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(aClient.Execute("dataset channel %u", aChannel) != nullptr, ret = kWpanStatus_SetFailed);
605*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(aClient.Execute("dataset panid %u", aPanId) != nullptr, ret = kWpanStatus_SetFailed);
606*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(aClient.Execute("dataset commit active") != nullptr, ret = kWpanStatus_SetFailed);
607*4a64e381SAndroid Build Coastguard Worker 
608*4a64e381SAndroid Build Coastguard Worker exit:
609*4a64e381SAndroid Build Coastguard Worker     return ret;
610*4a64e381SAndroid Build Coastguard Worker }
611*4a64e381SAndroid Build Coastguard Worker 
formActiveDataset(otbr::Web::OpenThreadClient & aClient,const std::string & aNetworkKey,const std::string & aNetworkName,const std::string & aPskc,uint16_t aChannel,uint64_t aExtPanId,uint16_t aPanId)612*4a64e381SAndroid Build Coastguard Worker int WpanService::formActiveDataset(otbr::Web::OpenThreadClient &aClient,
613*4a64e381SAndroid Build Coastguard Worker                                    const std::string           &aNetworkKey,
614*4a64e381SAndroid Build Coastguard Worker                                    const std::string           &aNetworkName,
615*4a64e381SAndroid Build Coastguard Worker                                    const std::string           &aPskc,
616*4a64e381SAndroid Build Coastguard Worker                                    uint16_t                     aChannel,
617*4a64e381SAndroid Build Coastguard Worker                                    uint64_t                     aExtPanId,
618*4a64e381SAndroid Build Coastguard Worker                                    uint16_t                     aPanId)
619*4a64e381SAndroid Build Coastguard Worker {
620*4a64e381SAndroid Build Coastguard Worker     int ret = kWpanStatus_Ok;
621*4a64e381SAndroid Build Coastguard Worker 
622*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(aClient.Execute("dataset init new") != nullptr, ret = kWpanStatus_SetFailed);
623*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(aClient.Execute("dataset networkkey %s", aNetworkKey.c_str()) != nullptr, ret = kWpanStatus_SetFailed);
624*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(aClient.Execute("dataset networkname %s", escapeOtCliEscapable(aNetworkName).c_str()) != nullptr,
625*4a64e381SAndroid Build Coastguard Worker                  ret = kWpanStatus_SetFailed);
626*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(aClient.Execute("dataset pskc %s", aPskc.c_str()) != nullptr, ret = kWpanStatus_SetFailed);
627*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(aClient.Execute("dataset channel %u", aChannel) != nullptr, ret = kWpanStatus_SetFailed);
628*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(aClient.Execute("dataset extpanid %016" PRIx64, aExtPanId) != nullptr, ret = kWpanStatus_SetFailed);
629*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(aClient.Execute("dataset panid %u", aPanId) != nullptr, ret = kWpanStatus_SetFailed);
630*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(aClient.Execute("dataset commit active") != nullptr, ret = kWpanStatus_SetFailed);
631*4a64e381SAndroid Build Coastguard Worker 
632*4a64e381SAndroid Build Coastguard Worker exit:
633*4a64e381SAndroid Build Coastguard Worker     return ret;
634*4a64e381SAndroid Build Coastguard Worker }
635*4a64e381SAndroid Build Coastguard Worker 
escapeOtCliEscapable(const std::string & aArg)636*4a64e381SAndroid Build Coastguard Worker std::string WpanService::escapeOtCliEscapable(const std::string &aArg)
637*4a64e381SAndroid Build Coastguard Worker {
638*4a64e381SAndroid Build Coastguard Worker     std::stringbuf strbuf;
639*4a64e381SAndroid Build Coastguard Worker 
640*4a64e381SAndroid Build Coastguard Worker     for (char c : aArg)
641*4a64e381SAndroid Build Coastguard Worker     {
642*4a64e381SAndroid Build Coastguard Worker         switch (c)
643*4a64e381SAndroid Build Coastguard Worker         {
644*4a64e381SAndroid Build Coastguard Worker         case ' ':
645*4a64e381SAndroid Build Coastguard Worker         case '\t':
646*4a64e381SAndroid Build Coastguard Worker         case '\r':
647*4a64e381SAndroid Build Coastguard Worker         case '\n':
648*4a64e381SAndroid Build Coastguard Worker         case '\\':
649*4a64e381SAndroid Build Coastguard Worker             strbuf.sputc('\\');
650*4a64e381SAndroid Build Coastguard Worker             // Fallthrough
651*4a64e381SAndroid Build Coastguard Worker         default:
652*4a64e381SAndroid Build Coastguard Worker             strbuf.sputc(c);
653*4a64e381SAndroid Build Coastguard Worker         }
654*4a64e381SAndroid Build Coastguard Worker     }
655*4a64e381SAndroid Build Coastguard Worker 
656*4a64e381SAndroid Build Coastguard Worker     return strbuf.str();
657*4a64e381SAndroid Build Coastguard Worker }
658*4a64e381SAndroid Build Coastguard Worker 
659*4a64e381SAndroid Build Coastguard Worker } // namespace Web
660*4a64e381SAndroid Build Coastguard Worker } // namespace otbr
661