Skip to content

Commit 2ec2679

Browse files
committed
- Move all serialization code to separate Serializer namespace and files.
- Generalize and improve JSON processing code. - Prevent mesh passwords from containing " characters to avoid messing up the JSON processing. - Improve documentation.
1 parent e64125a commit 2ec2679

14 files changed

+455
-223
lines changed

libraries/ESP8266WiFiMesh/examples/HelloEspnow/HelloEspnow.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ namespace TypeCast = MeshTypeConversionFunctions;
1919
https://arduino-esp8266.readthedocs.io/en/latest/PROGMEM.html
2020
*/
2121
constexpr char exampleMeshName[] PROGMEM = "MeshNode_"; // The name of the mesh network. Used as prefix for the node SSID and to find other network nodes in the example networkFilter and broadcastFilter functions below.
22-
constexpr char exampleWiFiPassword[] PROGMEM = "ChangeThisWiFiPassword_TODO"; // The password has to be min 8 and max 64 characters long, otherwise an AP which uses it will not be found during scans.
22+
constexpr char exampleWiFiPassword[] PROGMEM = "ChangeThisWiFiPassword_TODO"; // Note: " is an illegal character. The password has to be min 8 and max 64 characters long, otherwise an AP which uses it will not be found during scans.
2323

2424
// A custom encryption key is required when using encrypted ESP-NOW transmissions. There is always a default Kok set, but it can be replaced if desired.
2525
// All ESP-NOW keys below must match in an encrypted connection pair for encrypted communication to be possible.

libraries/ESP8266WiFiMesh/examples/HelloMesh/HelloMesh.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ namespace TypeCast = MeshTypeConversionFunctions;
2626
https://arduino-esp8266.readthedocs.io/en/latest/PROGMEM.html
2727
*/
2828
constexpr char exampleMeshName[] PROGMEM = "MeshNode_"; // The name of the mesh network. Used as prefix for the node SSID and to find other network nodes in the example networkFilter and broadcastFilter functions below.
29-
constexpr char exampleWiFiPassword[] PROGMEM = "ChangeThisWiFiPassword_TODO"; // The password has to be min 8 and max 64 characters long, otherwise an AP which uses it will not be found during scans.
29+
constexpr char exampleWiFiPassword[] PROGMEM = "ChangeThisWiFiPassword_TODO"; // Note: " is an illegal character. The password has to be min 8 and max 64 characters long, otherwise an AP which uses it will not be found during scans.
3030

3131
// A custom encryption key is required when using encrypted ESP-NOW transmissions. There is always a default Kok set, but it can be replaced if desired.
3232
// All ESP-NOW keys below must match in an encrypted connection pair for encrypted communication to be possible.

libraries/ESP8266WiFiMesh/examples/HelloTcpIp/HelloTcpIp.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ namespace TypeCast = MeshTypeConversionFunctions;
1919
https://arduino-esp8266.readthedocs.io/en/latest/PROGMEM.html
2020
*/
2121
constexpr char exampleMeshName[] PROGMEM = "MeshNode_";
22-
constexpr char exampleWiFiPassword[] PROGMEM = "ChangeThisWiFiPassword_TODO";
22+
constexpr char exampleWiFiPassword[] PROGMEM = "ChangeThisWiFiPassword_TODO"; // Note: " is an illegal character. The password has to be min 8 and max 64 characters long, otherwise an AP which uses it will not be found during scans.
2323

2424
unsigned int requestNumber = 0;
2525
unsigned int responseNumber = 0;

libraries/ESP8266WiFiMesh/src/EncryptedConnectionData.cpp

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "TypeConversionFunctions.h"
2828
#include "JsonTranslator.h"
2929
#include "MeshCryptoInterface.h"
30+
#include "Serializer.h"
3031

3132
namespace
3233
{
@@ -157,16 +158,8 @@ bool EncryptedConnectionData::desync() const { return _desync; }
157158

158159
String EncryptedConnectionData::serialize() const
159160
{
160-
// Returns: {"connectionState":{"duration":"123","password":"abc","ownSK":"1A2","peerSK":"3B4","peerStaMac":"F2","peerApMac":"E3"}}
161-
162-
return
163-
String(FPSTR(JsonTranslator::jsonConnectionState))
164-
+ (temporary() ? String(FPSTR(JsonTranslator::jsonDuration)) + '\"' + String(temporary()->remainingDuration()) + F("\",") : emptyString)
165-
+ FPSTR(JsonTranslator::jsonDesync) + '\"' + String(desync()) + F("\",")
166-
+ FPSTR(JsonTranslator::jsonOwnSessionKey) + '\"' + TypeCast::uint64ToString(getOwnSessionKey()) + F("\",")
167-
+ FPSTR(JsonTranslator::jsonPeerSessionKey) + '\"' + TypeCast::uint64ToString(getPeerSessionKey()) + F("\",")
168-
+ FPSTR(JsonTranslator::jsonPeerStaMac) + '\"' + TypeCast::macToString(_peerStaMac) + F("\",")
169-
+ FPSTR(JsonTranslator::jsonPeerApMac) + '\"' + TypeCast::macToString(_peerApMac) + F("\"}}");
161+
return Serializer:: serializeEncryptedConnection((temporary() ? String(temporary()->remainingDuration()) : emptyString), String(desync()), TypeCast::uint64ToString(getOwnSessionKey()),
162+
TypeCast::uint64ToString(getPeerSessionKey()), TypeCast::macToString(_peerStaMac), TypeCast::macToString(_peerApMac));
170163
}
171164

172165
const ExpiringTimeTracker *EncryptedConnectionData::temporary() const

libraries/ESP8266WiFiMesh/src/EspnowMeshBackend.cpp

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ extern "C" {
2727
#include "MutexTracker.h"
2828
#include "JsonTranslator.h"
2929
#include "MeshCryptoInterface.h"
30+
#include "EspnowUtility.h"
31+
#include "Serializer.h"
3032

3133
namespace
3234
{
@@ -1112,7 +1114,7 @@ TransmissionStatusType EspnowMeshBackend::espnowSendToNode(const String &message
11121114
TransmissionStatusType EspnowMeshBackend::espnowSendToNodeUnsynchronized(const String message, const uint8_t *targetBSSID, const char messageType, const uint64_t messageID, EspnowMeshBackend *espnowInstance)
11131115
{
11141116
using namespace EspnowProtocolInterpreter;
1115-
1117+
11161118
MutexTracker mutexTracker(_espnowSendToNodeMutex);
11171119
if(!mutexTracker.mutexCaptured())
11181120
{
@@ -1773,7 +1775,7 @@ EncryptedConnectionStatus EspnowMeshBackend::requestEncryptedConnectionKernel(co
17731775
requestMessage = encryptionRequestBuilder(requestNonce, existingTimeTracker);
17741776
else if(_ongoingPeerRequestResult == EncryptedConnectionStatus::SOFT_LIMIT_CONNECTION_ESTABLISHED)
17751777
// We will only get a soft limit connection. Adjust future actions based on this.
1776-
requestMessage = JsonTranslator::createEncryptionRequestHmacMessage(FPSTR(temporaryEncryptionRequestHeader), requestNonce, getEspnowHashKey(),
1778+
requestMessage = Serializer::createEncryptionRequestHmacMessage(FPSTR(temporaryEncryptionRequestHeader), requestNonce, getEspnowHashKey(),
17771779
hashKeyLength, getAutoEncryptionDuration());
17781780
else
17791781
assert(false && String(F("Unknown _ongoingPeerRequestResult during encrypted connection finalization!")));
@@ -1848,7 +1850,7 @@ String EspnowMeshBackend::defaultEncryptionRequestBuilder(const String &requestH
18481850
{
18491851
(void)existingTimeTracker; // This removes a "unused parameter" compiler warning. Does nothing else.
18501852

1851-
return JsonTranslator::createEncryptionRequestHmacMessage(requestHeader, requestNonce, hashKey, hashKeyLength, durationMs);
1853+
return Serializer::createEncryptionRequestHmacMessage(requestHeader, requestNonce, hashKey, hashKeyLength, durationMs);
18521854
}
18531855

18541856
String EspnowMeshBackend::flexibleEncryptionRequestBuilder(const uint32_t minDurationMs, const uint8_t *hashKey,
@@ -1860,7 +1862,7 @@ String EspnowMeshBackend::flexibleEncryptionRequestBuilder(const uint32_t minDur
18601862
uint32_t connectionDuration = minDurationMs >= existingTimeTracker.remainingDuration() ?
18611863
minDurationMs : existingTimeTracker.remainingDuration();
18621864

1863-
return createEncryptionRequestHmacMessage(FPSTR(temporaryEncryptionRequestHeader), requestNonce, hashKey, hashKeyLength, connectionDuration);
1865+
return Serializer::createEncryptionRequestHmacMessage(FPSTR(temporaryEncryptionRequestHeader), requestNonce, hashKey, hashKeyLength, connectionDuration);
18641866
}
18651867

18661868
EncryptedConnectionStatus EspnowMeshBackend::requestEncryptedConnection(const uint8_t *peerMac)
@@ -2437,13 +2439,13 @@ void EspnowMeshBackend::sendPeerRequestConfirmations(const ExpiringTimeTracker *
24372439
if(!existingEncryptedConnection &&
24382440
((reciprocalPeerRequest && encryptedConnections.size() >= maxEncryptedConnections) || (!reciprocalPeerRequest && reservedEncryptedConnections() >= maxEncryptedConnections)))
24392441
{
2440-
espnowSendToNodeUnsynchronized(JsonTranslator::createEncryptionRequestHmacMessage(FPSTR(maxConnectionsReachedHeader),
2442+
espnowSendToNodeUnsynchronized(Serializer::createEncryptionRequestHmacMessage(FPSTR(maxConnectionsReachedHeader),
24412443
confirmationsIterator->getPeerRequestNonce(), hashKey, hashKeyLength),
24422444
defaultBSSID, 'C', generateMessageID(nullptr)); // Generates a new message ID to avoid sending encrypted sessionKeys over unencrypted connections.
24432445

24442446
confirmationsIterator = peerRequestConfirmationsToSend.erase(confirmationsIterator);
24452447
}
2446-
else if(espnowSendToNodeUnsynchronized(JsonTranslator::createEncryptionRequestHmacMessage(FPSTR(basicConnectionInfoHeader),
2448+
else if(espnowSendToNodeUnsynchronized(Serializer::createEncryptionRequestHmacMessage(FPSTR(basicConnectionInfoHeader),
24472449
confirmationsIterator->getPeerRequestNonce(), hashKey, hashKeyLength),
24482450
sendToDefaultBSSID ? defaultBSSID : unencryptedBSSID, 'C', generateMessageID(nullptr)) // Generates a new message ID to avoid sending encrypted sessionKeys over unencrypted connections.
24492451
== TransmissionStatusType::TRANSMISSION_COMPLETE)
@@ -2475,7 +2477,7 @@ void EspnowMeshBackend::sendPeerRequestConfirmations(const ExpiringTimeTracker *
24752477
if(!existingEncryptedConnection)
24762478
{
24772479
// Send "node full" message
2478-
espnowSendToNodeUnsynchronized(JsonTranslator::createEncryptionRequestHmacMessage(FPSTR(maxConnectionsReachedHeader),
2480+
espnowSendToNodeUnsynchronized(Serializer::createEncryptionRequestHmacMessage(FPSTR(maxConnectionsReachedHeader),
24792481
confirmationsIterator->getPeerRequestNonce(), hashKey, hashKeyLength),
24802482
defaultBSSID, 'C', generateMessageID(nullptr)); // Generates a new message ID to avoid sending encrypted sessionKeys over unencrypted connections.
24812483
}
@@ -2503,7 +2505,7 @@ void EspnowMeshBackend::sendPeerRequestConfirmations(const ExpiringTimeTracker *
25032505

25042506
// Send password and keys.
25052507
// Probably no need to know which connection type to use, that is stored in request node and will be sent over for finalization.
2506-
espnowSendToNodeUnsynchronized(JsonTranslator::createEncryptedConnectionInfo(messageHeader,
2508+
espnowSendToNodeUnsynchronized(Serializer::createEncryptedConnectionInfo(messageHeader,
25072509
confirmationsIterator->getPeerRequestNonce(), confirmationsIterator->getAuthenticationPassword(),
25082510
existingEncryptedConnection->getOwnSessionKey(), existingEncryptedConnection->getPeerSessionKey()),
25092511
defaultBSSID, 'C', generateMessageID(nullptr)); // Generates a new message ID to avoid sending encrypted sessionKeys over unencrypted connections.
@@ -2678,12 +2680,8 @@ void EspnowMeshBackend::resetTransmissionFailRate()
26782680
}
26792681

26802682
String EspnowMeshBackend::serializeUnencryptedConnection()
2681-
{
2682-
using namespace JsonTranslator;
2683-
2684-
// Returns: {"connectionState":{"unsyncMsgID":"123"}}
2685-
2686-
return String(FPSTR(jsonConnectionState)) + createJsonEndPair(FPSTR(jsonUnsynchronizedMessageID), String(_unsynchronizedMessageID));
2683+
{
2684+
return Serializer::serializeUnencryptedConnection(String(_unsynchronizedMessageID));
26872685
}
26882686

26892687
String EspnowMeshBackend::serializeEncryptedConnection(const uint8_t *peerMac)

libraries/ESP8266WiFiMesh/src/EspnowMeshBackend.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -657,11 +657,11 @@ class EspnowMeshBackend : public MeshBackendBase {
657657
* @param intervalMs The time to wait for an ack after having made an ESP-NOW transmission, in milliseconds. Defaults to 15 ms.
658658
*/
659659
static void setEspnowRetransmissionInterval(const uint32_t intervalMs);
660-
static uint32_t getEspnowRetransmissionInterval();
660+
static uint32_t getEspnowRetransmissionInterval();
661661

662662
// The maximum amount of time each of the two stages in an encrypted connection request may take.
663663
static void setEncryptionRequestTimeout(const uint32_t timeoutMs);
664-
static uint32_t getEncryptionRequestTimeout();
664+
static uint32_t getEncryptionRequestTimeout();
665665

666666
void setAutoEncryptionDuration(const uint32_t duration);
667667
uint32_t getAutoEncryptionDuration() const;
@@ -1217,7 +1217,7 @@ class EspnowMeshBackend : public MeshBackendBase {
12171217
* @param peerMac The MAC of the node with which an encrypted connection should be established.
12181218
* @param encryptionRequestBuilder A function which is responsible for constructing the request message to send.
12191219
* Called twice when the request is successful. First to build the initial request message and then to build the connection verification message.
1220-
* The request message should typically be of the form: JsonTranslator::createEncryptionRequestIntro() + JsonTranslator::createEncryptionRequestEnding().
1220+
* The request message should typically be of the form found in Serializer::createEncryptionRequestHmacMessage.
12211221
* @return The ultimate status of the requested encrypted connection, as EncryptedConnectionStatus.
12221222
*/
12231223
EncryptedConnectionStatus requestEncryptedConnectionKernel(const uint8_t *peerMac, const encryptionRequestBuilderType &encryptionRequestBuilder);

libraries/ESP8266WiFiMesh/src/FloodingMesh.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "FloodingMesh.h"
2626
#include "TypeConversionFunctions.h"
2727
#include "JsonTranslator.h"
28+
#include "Serializer.h"
2829

2930
namespace
3031
{
@@ -153,16 +154,11 @@ void FloodingMesh::performMeshInstanceMaintenance()
153154

154155
String FloodingMesh::serializeMeshState() const
155156
{
156-
using namespace JsonTranslator;
157-
158-
// Returns: {"meshState":{"connectionState":{"unsyncMsgID":"123"},"meshMsgCount":"123"}}
159-
160157
String connectionState = getEspnowMeshBackendConst().serializeUnencryptedConnection();
158+
uint32_t unsyncMsgID = 0;
159+
JsonTranslator::getUnsynchronizedMessageID(connectionState, unsyncMsgID);
161160

162-
return
163-
String(F("{\"meshState\":{"))
164-
+ connectionState.substring(1, connectionState.length() - 1) + String(',')
165-
+ createJsonEndPair(FPSTR(jsonMeshMessageCount), String(_messageCount));
161+
return Serializer::serializeMeshState(String(unsyncMsgID), String(_messageCount));
166162
}
167163

168164
void FloodingMesh::loadMeshState(const String &serializedMeshState)

0 commit comments

Comments
 (0)