1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-07-23 08:45:22 +03:00
Files
esp8266/libraries/ESP8266WiFiMesh/src/JsonTranslator.cpp
Anders 40e1f02ffb - Split most of the EspnowMeshBackend code into utility files and the new ConditionalPrinter, EspnowDatabase, EspnowConnectionManager, EspnowTransmitter and EspnowEncryptionBroker classes.
- Improve mutex handling.

- Move verifyEncryptionRequestHmac function from JsonTranslator to EspnowEncryptionBroker.

- Remove UtilityMethods.cpp.
2020-05-15 20:33:08 +02:00

264 lines
7.5 KiB
C++

/*
* Copyright (C) 2019 Anders Löfgren
*
* License (MIT license):
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "JsonTranslator.h"
#include "EspnowProtocolInterpreter.h"
#include "TypeConversionFunctions.h"
namespace
{
namespace TypeCast = MeshTypeConversionFunctions;
bool getMac(const String &jsonString, const String &valueIdentifier, uint8_t *resultArray)
{
String jsonValue;
bool decoded = JsonTranslator::decode(jsonString, valueIdentifier, jsonValue);
if(jsonValue.length() != 12)
decoded = false; // Mac String is always 12 characters long
if(decoded)
TypeCast::stringToMac(jsonValue, resultArray);
return decoded;
}
}
namespace JsonTranslator
{
int32_t getStartIndex(const String &jsonString, const String &valueIdentifier, const int32_t searchStartIndex)
{
int32_t startIndex = jsonString.indexOf(String('"') + valueIdentifier + F("\":"), searchStartIndex);
if(startIndex < 0)
return startIndex;
startIndex += valueIdentifier.length() + 3; // Do not include valueIdentifier and associated characters
return startIndex;
}
int32_t getEndIndex(const String &jsonString, const int32_t searchStartIndex)
{
int32_t endIndex = -1;
if(jsonString[searchStartIndex] == '"')
{
endIndex = jsonString.indexOf('"', searchStartIndex + 1);
}
else if(jsonString[searchStartIndex] == '{')
{
uint32_t depth = 1;
bool withinString = false;
for(uint32_t index = searchStartIndex + 1; depth != 0 && index < jsonString.length(); ++index)
{
if(jsonString[index] == '"')
withinString = !withinString;
else if(!withinString)
{
if(jsonString[index] == '{')
++depth;
else if(jsonString[index] == '}')
--depth;
}
if(depth == 0)
{
assert(index < 0x80000000); // Must avoid int32_t overflow
endIndex = index;
}
}
}
return endIndex;
}
String encode(std::initializer_list<String> identifiersAndValues)
{
assert(identifiersAndValues.size() % 2 == 0); // List must consist of identifer-value pairs.
String result = String('{');
bool isIdentifier = true;
for(String element : identifiersAndValues)
{
bool isObject = !isIdentifier && element[0] == '{';
if(isObject)
result += element;
else
result += String('"') + element + String('"');
if(isIdentifier)
result += ':';
else
result += ',';
isIdentifier = !isIdentifier;
}
result[result.length() - 1] = '}';
return result;
}
String encodeLiterally(std::initializer_list<String> identifiersAndValues)
{
assert(identifiersAndValues.size() % 2 == 0); // List must consist of identifer-value pairs.
String result = String('{');
bool isIdentifier = true;
for(String element : identifiersAndValues)
{
if(isIdentifier)
result += String('"') + element + String('"') + ':';
else
result += element + ',';
isIdentifier = !isIdentifier;
}
result[result.length() - 1] = '}';
return result;
}
bool decode(const String &jsonString, const String &valueIdentifier, String &value)
{
int32_t startIndex = getStartIndex(jsonString, valueIdentifier);
if(startIndex < 0)
return false;
int32_t endIndex = getEndIndex(jsonString, startIndex);
if(endIndex < 0)
return false;
if(jsonString[startIndex] == '"')
++startIndex; // Should not include starting "
else if(jsonString[startIndex] == '{')
++endIndex; // Should include ending }
else
assert(false && F("Illegal JSON starting character!"));
value = jsonString.substring(startIndex, endIndex);
return true;
}
bool decode(const String &jsonString, const String &valueIdentifier, uint32_t &value)
{
String jsonValue;
bool decoded = decode(jsonString, valueIdentifier, jsonValue);
if(decoded)
value = strtoul(jsonValue.c_str(), nullptr, 0); // strtoul stops reading input when an invalid character is discovered.
return decoded;
}
bool decodeRadix(const String &jsonString, const String &valueIdentifier, uint64_t &value, const uint8_t radix)
{
String jsonValue;
bool decoded = decode(jsonString, valueIdentifier, jsonValue);
if(decoded)
value = TypeCast::stringToUint64(jsonValue, radix);
return decoded;
}
bool getConnectionState(const String &jsonString, String &result)
{
return decode(jsonString, FPSTR(jsonConnectionState), result);
}
bool getPassword(const String &jsonString, String &result)
{
return decode(jsonString, FPSTR(jsonPassword), result);
}
bool getOwnSessionKey(const String &jsonString, uint64_t &result)
{
return decodeRadix(jsonString, FPSTR(jsonOwnSessionKey), result);
}
bool getPeerSessionKey(const String &jsonString, uint64_t &result)
{
return decodeRadix(jsonString, FPSTR(jsonPeerSessionKey), result);
}
bool getPeerStaMac(const String &jsonString, uint8_t *resultArray)
{
return getMac(jsonString, FPSTR(jsonPeerStaMac), resultArray);
}
bool getPeerApMac(const String &jsonString, uint8_t *resultArray)
{
return getMac(jsonString, FPSTR(jsonPeerApMac), resultArray);
}
bool getDuration(const String &jsonString, uint32_t &result)
{
return decode(jsonString, FPSTR(jsonDuration), result);
}
bool getNonce(const String &jsonString, String &result)
{
return decode(jsonString, FPSTR(jsonNonce), result);
}
bool getHmac(const String &jsonString, String &result)
{
return decode(jsonString, FPSTR(jsonHmac), result);
}
bool getDesync(const String &jsonString, bool &result)
{
String jsonValue;
bool decoded = decode(jsonString, FPSTR(jsonDesync), jsonValue);
if(decoded)
result = bool(strtoul(jsonValue.c_str(), nullptr, 0)); // strtoul stops reading input when an invalid character is discovered.
return decoded;
}
bool getUnsynchronizedMessageID(const String &jsonString, uint32_t &result)
{
return decode(jsonString, FPSTR(jsonUnsynchronizedMessageID), result);
}
bool getMeshMessageCount(const String &jsonString, uint16_t &result)
{
uint32_t longResult = 0;
bool decoded = decode(jsonString, FPSTR(jsonMeshMessageCount), longResult);
if(longResult > 65535) // Must fit within uint16_t
decoded = false;
if(decoded)
result = longResult;
return decoded;
}
}