• 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 "rest/json.hpp"
30 
31 #include "common/code_utils.hpp"
32 #include "common/types.hpp"
33 
34 extern "C" {
35 #include <cJSON.h>
36 }
37 
38 namespace otbr {
39 namespace rest {
40 namespace Json {
41 
Bytes2HexJson(const uint8_t * aBytes,uint8_t aLength)42 static cJSON *Bytes2HexJson(const uint8_t *aBytes, uint8_t aLength)
43 {
44     char hex[2 * aLength + 1];
45 
46     otbr::Utils::Bytes2Hex(aBytes, aLength, hex);
47     hex[2 * aLength] = '\0';
48 
49     return cJSON_CreateString(hex);
50 }
51 
String2JsonString(const std::string & aString)52 std::string String2JsonString(const std::string &aString)
53 {
54     std::string ret;
55     cJSON *     json    = nullptr;
56     char *      jsonOut = nullptr;
57 
58     VerifyOrExit(aString.size() > 0);
59 
60     json    = cJSON_CreateString(aString.c_str());
61     jsonOut = cJSON_Print(json);
62     ret     = jsonOut;
63     if (jsonOut != nullptr)
64     {
65         cJSON_free(jsonOut);
66         jsonOut = nullptr;
67     }
68 
69     cJSON_Delete(json);
70 
71 exit:
72     return ret;
73 }
74 
Json2String(const cJSON * aJson)75 std::string Json2String(const cJSON *aJson)
76 {
77     std::string ret;
78     char *      jsonOut = nullptr;
79 
80     VerifyOrExit(aJson != nullptr);
81 
82     jsonOut = cJSON_Print(aJson);
83     ret     = jsonOut;
84     if (jsonOut != nullptr)
85     {
86         cJSON_free(jsonOut);
87         jsonOut = nullptr;
88     }
89 
90 exit:
91     return ret;
92 }
93 
CString2Json(const char * aString)94 static cJSON *CString2Json(const char *aString)
95 {
96     return cJSON_CreateString(aString);
97 }
98 
Mode2Json(const otLinkModeConfig & aMode)99 static cJSON *Mode2Json(const otLinkModeConfig &aMode)
100 {
101     cJSON *mode = cJSON_CreateObject();
102 
103     cJSON_AddItemToObject(mode, "RxOnWhenIdle", cJSON_CreateNumber(aMode.mRxOnWhenIdle));
104     cJSON_AddItemToObject(mode, "DeviceType", cJSON_CreateNumber(aMode.mDeviceType));
105     cJSON_AddItemToObject(mode, "NetworkData", cJSON_CreateNumber(aMode.mNetworkData));
106 
107     return mode;
108 }
109 
IpAddr2Json(const otIp6Address & aAddress)110 static cJSON *IpAddr2Json(const otIp6Address &aAddress)
111 {
112     Ip6Address addr(aAddress.mFields.m8);
113 
114     return cJSON_CreateString(addr.ToString().c_str());
115 }
116 
ChildTableEntry2Json(const otNetworkDiagChildEntry & aChildEntry)117 static cJSON *ChildTableEntry2Json(const otNetworkDiagChildEntry &aChildEntry)
118 {
119     cJSON *childEntry = cJSON_CreateObject();
120 
121     cJSON_AddItemToObject(childEntry, "ChildId", cJSON_CreateNumber(aChildEntry.mChildId));
122     cJSON_AddItemToObject(childEntry, "Timeout", cJSON_CreateNumber(aChildEntry.mTimeout));
123 
124     cJSON *mode = Mode2Json(aChildEntry.mMode);
125     cJSON_AddItemToObject(childEntry, "Mode", mode);
126 
127     return childEntry;
128 }
129 
MacCounters2Json(const otNetworkDiagMacCounters & aMacCounters)130 static cJSON *MacCounters2Json(const otNetworkDiagMacCounters &aMacCounters)
131 {
132     cJSON *macCounters = cJSON_CreateObject();
133 
134     cJSON_AddItemToObject(macCounters, "IfInUnknownProtos", cJSON_CreateNumber(aMacCounters.mIfInUnknownProtos));
135     cJSON_AddItemToObject(macCounters, "IfInErrors", cJSON_CreateNumber(aMacCounters.mIfInErrors));
136     cJSON_AddItemToObject(macCounters, "IfOutErrors", cJSON_CreateNumber(aMacCounters.mIfOutErrors));
137     cJSON_AddItemToObject(macCounters, "IfInUcastPkts", cJSON_CreateNumber(aMacCounters.mIfInUcastPkts));
138     cJSON_AddItemToObject(macCounters, "IfInBroadcastPkts", cJSON_CreateNumber(aMacCounters.mIfInBroadcastPkts));
139     cJSON_AddItemToObject(macCounters, "IfInDiscards", cJSON_CreateNumber(aMacCounters.mIfInDiscards));
140     cJSON_AddItemToObject(macCounters, "IfOutUcastPkts", cJSON_CreateNumber(aMacCounters.mIfOutUcastPkts));
141     cJSON_AddItemToObject(macCounters, "IfOutBroadcastPkts", cJSON_CreateNumber(aMacCounters.mIfOutBroadcastPkts));
142     cJSON_AddItemToObject(macCounters, "IfOutDiscards", cJSON_CreateNumber(aMacCounters.mIfOutDiscards));
143 
144     return macCounters;
145 }
146 
Connectivity2Json(const otNetworkDiagConnectivity & aConnectivity)147 static cJSON *Connectivity2Json(const otNetworkDiagConnectivity &aConnectivity)
148 {
149     cJSON *connectivity = cJSON_CreateObject();
150 
151     cJSON_AddItemToObject(connectivity, "ParentPriority", cJSON_CreateNumber(aConnectivity.mParentPriority));
152     cJSON_AddItemToObject(connectivity, "LinkQuality3", cJSON_CreateNumber(aConnectivity.mLinkQuality3));
153     cJSON_AddItemToObject(connectivity, "LinkQuality2", cJSON_CreateNumber(aConnectivity.mLinkQuality2));
154     cJSON_AddItemToObject(connectivity, "LinkQuality1", cJSON_CreateNumber(aConnectivity.mLinkQuality1));
155     cJSON_AddItemToObject(connectivity, "LeaderCost", cJSON_CreateNumber(aConnectivity.mLeaderCost));
156     cJSON_AddItemToObject(connectivity, "IdSequence", cJSON_CreateNumber(aConnectivity.mIdSequence));
157     cJSON_AddItemToObject(connectivity, "ActiveRouters", cJSON_CreateNumber(aConnectivity.mActiveRouters));
158     cJSON_AddItemToObject(connectivity, "SedBufferSize", cJSON_CreateNumber(aConnectivity.mSedBufferSize));
159     cJSON_AddItemToObject(connectivity, "SedDatagramCount", cJSON_CreateNumber(aConnectivity.mSedDatagramCount));
160 
161     return connectivity;
162 }
163 
RouteData2Json(const otNetworkDiagRouteData & aRouteData)164 static cJSON *RouteData2Json(const otNetworkDiagRouteData &aRouteData)
165 {
166     cJSON *routeData = cJSON_CreateObject();
167 
168     cJSON_AddItemToObject(routeData, "RouteId", cJSON_CreateNumber(aRouteData.mRouterId));
169     cJSON_AddItemToObject(routeData, "LinkQualityOut", cJSON_CreateNumber(aRouteData.mLinkQualityOut));
170     cJSON_AddItemToObject(routeData, "LinkQualityIn", cJSON_CreateNumber(aRouteData.mLinkQualityIn));
171     cJSON_AddItemToObject(routeData, "RouteCost", cJSON_CreateNumber(aRouteData.mRouteCost));
172 
173     return routeData;
174 }
175 
Route2Json(const otNetworkDiagRoute & aRoute)176 static cJSON *Route2Json(const otNetworkDiagRoute &aRoute)
177 {
178     cJSON *route = cJSON_CreateObject();
179 
180     cJSON_AddItemToObject(route, "IdSequence", cJSON_CreateNumber(aRoute.mIdSequence));
181 
182     cJSON *RouteData = cJSON_CreateArray();
183     for (uint16_t i = 0; i < aRoute.mRouteCount; ++i)
184     {
185         cJSON *RouteDatavalue = RouteData2Json(aRoute.mRouteData[i]);
186         cJSON_AddItemToArray(RouteData, RouteDatavalue);
187     }
188 
189     cJSON_AddItemToObject(route, "RouteData", RouteData);
190 
191     return route;
192 }
193 
LeaderData2Json(const otLeaderData & aLeaderData)194 static cJSON *LeaderData2Json(const otLeaderData &aLeaderData)
195 {
196     cJSON *leaderData = cJSON_CreateObject();
197 
198     cJSON_AddItemToObject(leaderData, "PartitionId", cJSON_CreateNumber(aLeaderData.mPartitionId));
199     cJSON_AddItemToObject(leaderData, "Weighting", cJSON_CreateNumber(aLeaderData.mWeighting));
200     cJSON_AddItemToObject(leaderData, "DataVersion", cJSON_CreateNumber(aLeaderData.mDataVersion));
201     cJSON_AddItemToObject(leaderData, "StableDataVersion", cJSON_CreateNumber(aLeaderData.mStableDataVersion));
202     cJSON_AddItemToObject(leaderData, "LeaderRouterId", cJSON_CreateNumber(aLeaderData.mLeaderRouterId));
203 
204     return leaderData;
205 }
206 
IpAddr2JsonString(const otIp6Address & aAddress)207 std::string IpAddr2JsonString(const otIp6Address &aAddress)
208 {
209     std::string ret;
210     cJSON *     ipAddr = IpAddr2Json(aAddress);
211 
212     ret = Json2String(ipAddr);
213     cJSON_Delete(ipAddr);
214 
215     return ret;
216 }
217 
Node2JsonString(const NodeInfo & aNode)218 std::string Node2JsonString(const NodeInfo &aNode)
219 {
220     cJSON *     node = cJSON_CreateObject();
221     std::string ret;
222 
223     cJSON_AddItemToObject(node, "State", cJSON_CreateNumber(aNode.mRole));
224     cJSON_AddItemToObject(node, "NumOfRouter", cJSON_CreateNumber(aNode.mNumOfRouter));
225     cJSON_AddItemToObject(node, "RlocAddress", IpAddr2Json(aNode.mRlocAddress));
226     cJSON_AddItemToObject(node, "ExtAddress", Bytes2HexJson(aNode.mExtAddress, OT_EXT_ADDRESS_SIZE));
227     cJSON_AddItemToObject(node, "NetworkName", cJSON_CreateString(aNode.mNetworkName.c_str()));
228     cJSON_AddItemToObject(node, "Rloc16", cJSON_CreateNumber(aNode.mRloc16));
229     cJSON_AddItemToObject(node, "LeaderData", LeaderData2Json(aNode.mLeaderData));
230     cJSON_AddItemToObject(node, "ExtPanId", Bytes2HexJson(aNode.mExtPanId, OT_EXT_PAN_ID_SIZE));
231 
232     ret = Json2String(node);
233     cJSON_Delete(node);
234 
235     return ret;
236 }
237 
Diag2JsonString(const std::vector<std::vector<otNetworkDiagTlv>> & aDiagSet)238 std::string Diag2JsonString(const std::vector<std::vector<otNetworkDiagTlv>> &aDiagSet)
239 {
240     cJSON *     diagInfo          = cJSON_CreateArray();
241     cJSON *     diagInfoOfOneNode = nullptr;
242     cJSON *     addrList          = nullptr;
243     cJSON *     tableList         = nullptr;
244     std::string ret;
245     uint64_t    timeout;
246 
247     for (auto diagItem : aDiagSet)
248     {
249         diagInfoOfOneNode = cJSON_CreateObject();
250         for (auto diagTlv : diagItem)
251         {
252             switch (diagTlv.mType)
253             {
254             case OT_NETWORK_DIAGNOSTIC_TLV_EXT_ADDRESS:
255 
256                 cJSON_AddItemToObject(diagInfoOfOneNode, "ExtAddress",
257                                       Bytes2HexJson(diagTlv.mData.mExtAddress.m8, OT_EXT_ADDRESS_SIZE));
258 
259                 break;
260             case OT_NETWORK_DIAGNOSTIC_TLV_SHORT_ADDRESS:
261 
262                 cJSON_AddItemToObject(diagInfoOfOneNode, "Rloc16", cJSON_CreateNumber(diagTlv.mData.mAddr16));
263 
264                 break;
265             case OT_NETWORK_DIAGNOSTIC_TLV_MODE:
266 
267                 cJSON_AddItemToObject(diagInfoOfOneNode, "Mode", Mode2Json(diagTlv.mData.mMode));
268 
269                 break;
270             case OT_NETWORK_DIAGNOSTIC_TLV_TIMEOUT:
271 
272                 timeout = static_cast<uint64_t>(diagTlv.mData.mTimeout);
273                 cJSON_AddItemToObject(diagInfoOfOneNode, "Timeout", cJSON_CreateNumber(timeout));
274 
275                 break;
276             case OT_NETWORK_DIAGNOSTIC_TLV_CONNECTIVITY:
277 
278                 cJSON_AddItemToObject(diagInfoOfOneNode, "Connectivity",
279                                       Connectivity2Json(diagTlv.mData.mConnectivity));
280 
281                 break;
282             case OT_NETWORK_DIAGNOSTIC_TLV_ROUTE:
283 
284                 cJSON_AddItemToObject(diagInfoOfOneNode, "Route", Route2Json(diagTlv.mData.mRoute));
285 
286                 break;
287             case OT_NETWORK_DIAGNOSTIC_TLV_LEADER_DATA:
288 
289                 cJSON_AddItemToObject(diagInfoOfOneNode, "LeaderData", LeaderData2Json(diagTlv.mData.mLeaderData));
290 
291                 break;
292             case OT_NETWORK_DIAGNOSTIC_TLV_NETWORK_DATA:
293 
294                 cJSON_AddItemToObject(diagInfoOfOneNode, "NetworkData",
295                                       Bytes2HexJson(diagTlv.mData.mNetworkData.m8, diagTlv.mData.mNetworkData.mCount));
296 
297                 break;
298             case OT_NETWORK_DIAGNOSTIC_TLV_IP6_ADDR_LIST:
299 
300                 addrList = cJSON_CreateArray();
301 
302                 for (uint16_t i = 0; i < diagTlv.mData.mIp6AddrList.mCount; ++i)
303                 {
304                     cJSON_AddItemToArray(addrList, IpAddr2Json(diagTlv.mData.mIp6AddrList.mList[i]));
305                 }
306                 cJSON_AddItemToObject(diagInfoOfOneNode, "IP6AddressList", addrList);
307 
308                 break;
309             case OT_NETWORK_DIAGNOSTIC_TLV_MAC_COUNTERS:
310 
311                 cJSON_AddItemToObject(diagInfoOfOneNode, "MACCounters", MacCounters2Json(diagTlv.mData.mMacCounters));
312 
313                 break;
314             case OT_NETWORK_DIAGNOSTIC_TLV_BATTERY_LEVEL:
315 
316                 cJSON_AddItemToObject(diagInfoOfOneNode, "BatteryLevel",
317                                       cJSON_CreateNumber(diagTlv.mData.mBatteryLevel));
318 
319                 break;
320             case OT_NETWORK_DIAGNOSTIC_TLV_SUPPLY_VOLTAGE:
321 
322                 cJSON_AddItemToObject(diagInfoOfOneNode, "SupplyVoltage",
323                                       cJSON_CreateNumber(diagTlv.mData.mSupplyVoltage));
324 
325                 break;
326             case OT_NETWORK_DIAGNOSTIC_TLV_CHILD_TABLE:
327 
328                 tableList = cJSON_CreateArray();
329 
330                 for (uint16_t i = 0; i < diagTlv.mData.mChildTable.mCount; ++i)
331                 {
332                     cJSON_AddItemToArray(tableList, ChildTableEntry2Json(diagTlv.mData.mChildTable.mTable[i]));
333                 }
334 
335                 cJSON_AddItemToObject(diagInfoOfOneNode, "ChildTable", tableList);
336 
337                 break;
338             case OT_NETWORK_DIAGNOSTIC_TLV_CHANNEL_PAGES:
339 
340                 cJSON_AddItemToObject(
341                     diagInfoOfOneNode, "ChannelPages",
342                     Bytes2HexJson(diagTlv.mData.mChannelPages.m8, diagTlv.mData.mChannelPages.mCount));
343 
344                 break;
345             case OT_NETWORK_DIAGNOSTIC_TLV_MAX_CHILD_TIMEOUT:
346 
347                 cJSON_AddItemToObject(diagInfoOfOneNode, "MaxChildTimeout",
348                                       cJSON_CreateNumber(diagTlv.mData.mMaxChildTimeout));
349 
350                 break;
351             default:
352                 break;
353             }
354         }
355         cJSON_AddItemToArray(diagInfo, diagInfoOfOneNode);
356     }
357 
358     ret = Json2String(diagInfo);
359 
360     cJSON_Delete(diagInfo);
361 
362     return ret;
363 }
364 
Bytes2HexJsonString(const uint8_t * aBytes,uint8_t aLength)365 std::string Bytes2HexJsonString(const uint8_t *aBytes, uint8_t aLength)
366 {
367     cJSON *     hex = Bytes2HexJson(aBytes, aLength);
368     std::string ret = Json2String(hex);
369 
370     cJSON_Delete(hex);
371 
372     return ret;
373 }
374 
Number2JsonString(const uint32_t & aNumber)375 std::string Number2JsonString(const uint32_t &aNumber)
376 {
377     cJSON *     number = cJSON_CreateNumber(aNumber);
378     std::string ret    = Json2String(number);
379 
380     cJSON_Delete(number);
381 
382     return ret;
383 }
384 
Mode2JsonString(const otLinkModeConfig & aMode)385 std::string Mode2JsonString(const otLinkModeConfig &aMode)
386 {
387     cJSON *     mode = Mode2Json(aMode);
388     std::string ret  = Json2String(mode);
389 
390     cJSON_Delete(mode);
391 
392     return ret;
393 }
394 
Connectivity2JsonString(const otNetworkDiagConnectivity & aConnectivity)395 std::string Connectivity2JsonString(const otNetworkDiagConnectivity &aConnectivity)
396 {
397     cJSON *     connectivity = Connectivity2Json(aConnectivity);
398     std::string ret          = Json2String(connectivity);
399 
400     cJSON_Delete(connectivity);
401 
402     return ret;
403 }
404 
RouteData2JsonString(const otNetworkDiagRouteData & aRouteData)405 std::string RouteData2JsonString(const otNetworkDiagRouteData &aRouteData)
406 {
407     cJSON *     routeData = RouteData2Json(aRouteData);
408     std::string ret       = Json2String(routeData);
409 
410     cJSON_Delete(routeData);
411 
412     return ret;
413 }
414 
Route2JsonString(const otNetworkDiagRoute & aRoute)415 std::string Route2JsonString(const otNetworkDiagRoute &aRoute)
416 {
417     cJSON *     route = Route2Json(aRoute);
418     std::string ret   = Json2String(route);
419 
420     cJSON_Delete(route);
421 
422     return ret;
423 }
424 
LeaderData2JsonString(const otLeaderData & aLeaderData)425 std::string LeaderData2JsonString(const otLeaderData &aLeaderData)
426 {
427     cJSON *     leaderData = LeaderData2Json(aLeaderData);
428     std::string ret        = Json2String(leaderData);
429 
430     cJSON_Delete(leaderData);
431 
432     return ret;
433 }
434 
MacCounters2JsonString(const otNetworkDiagMacCounters & aMacCounters)435 std::string MacCounters2JsonString(const otNetworkDiagMacCounters &aMacCounters)
436 {
437     cJSON *     macCounters = MacCounters2Json(aMacCounters);
438     std::string ret         = Json2String(macCounters);
439 
440     cJSON_Delete(macCounters);
441 
442     return ret;
443 }
444 
ChildTableEntry2JsonString(const otNetworkDiagChildEntry & aChildEntry)445 std::string ChildTableEntry2JsonString(const otNetworkDiagChildEntry &aChildEntry)
446 {
447     cJSON *     childEntry = ChildTableEntry2Json(aChildEntry);
448     std::string ret        = Json2String(childEntry);
449 
450     cJSON_Delete(childEntry);
451 
452     return ret;
453 }
454 
CString2JsonString(const char * aCString)455 std::string CString2JsonString(const char *aCString)
456 {
457     cJSON *     cString = CString2Json(aCString);
458     std::string ret     = Json2String(cString);
459 
460     cJSON_Delete(cString);
461 
462     return ret;
463 }
464 
Error2JsonString(HttpStatusCode aErrorCode,std::string aErrorMessage)465 std::string Error2JsonString(HttpStatusCode aErrorCode, std::string aErrorMessage)
466 {
467     std::string ret;
468     cJSON *     error = cJSON_CreateObject();
469 
470     cJSON_AddItemToObject(error, "ErrorCode", cJSON_CreateNumber(static_cast<int16_t>(aErrorCode)));
471     cJSON_AddItemToObject(error, "ErrorMessage", cJSON_CreateString(aErrorMessage.c_str()));
472 
473     ret = Json2String(error);
474 
475     cJSON_Delete(error);
476 
477     return ret;
478 }
479 
480 } // namespace Json
481 } // namespace rest
482 } // namespace otbr
483