Skip to content

WiFi Mesh Update 2.2 #6280

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 41 commits into from
Mar 14, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
d20177a
- Add new ESP-NOW mesh backend.
aerlon Jul 10, 2019
235b02e
Merge branch 'master' into wifi_mesh_update_2.2
earlephilhower Jul 28, 2019
26e626d
Merge branch 'master' into wifi_mesh_update_2.2
aerlon Aug 10, 2019
5834c54
- Add broadcast functionality.
aerlon Aug 10, 2019
2576a09
Merge branch 'master' into wifi_mesh_update_2.2
aerlon Sep 17, 2019
86025c7
- Make each mesh backend use a unique NetworkInfo class and separate …
aerlon Sep 18, 2019
b0ef919
Merge branch 'master' into wifi_mesh_update_2.2
aerlon Oct 29, 2019
f8ec4f1
- Make connectionQueue(), latestTransmissionOutcomes() and latestTran…
aerlon Oct 31, 2019
7ca5a7e
Fix conflict with master branch.
aerlon Nov 1, 2019
8194197
Even better fix of conflict with master branch.
aerlon Nov 1, 2019
176f285
Fix space.
aerlon Nov 1, 2019
6b76368
- Add working FloodingMesh. Unencrypted broadcasts should work well, …
aerlon Nov 3, 2019
78812a7
- Add HelloTcpIp.ino example for the TcpIpMeshBackend.
aerlon Nov 3, 2019
afc88f2
- Improve HelloMesh.ino.
aerlon Nov 4, 2019
3132325
- Replace Crypto files with CryptoInterface which uses BearSSL as a c…
aerlon Nov 5, 2019
2fef67d
- Generalize CryptoInterface.
aerlon Nov 10, 2019
962a23d
- Make it possible to transfer Strings containing null values via ESP…
aerlon Dec 4, 2019
a49f047
- Move all Strings to flash and optimize String usage, saving 4-5 kB …
aerlon Dec 21, 2019
16801f3
- Rework ExpiringTimeTracker to be based on PolledTimeout.
aerlon Mar 5, 2020
1dcd4c4
- Fix even more merge conflicts.
aerlon Mar 5, 2020
548d702
Merge branch 'master' into wifi_mesh_update_2.2
aerlon Mar 5, 2020
a24b8d2
Merge branch 'master' into wifi_mesh_update_2.2
devyte Apr 17, 2020
effcc3a
- Make everything const by default.
aerlon Apr 29, 2020
e64125a
- Move globals to anonymous namespaces.
aerlon May 5, 2020
2ec2679
- Move all serialization code to separate Serializer namespace and fi…
aerlon May 10, 2020
d01e639
- Fix build error.
aerlon May 11, 2020
3f5495b
Merge branch 'master' into wifi_mesh_update_2.2
aerlon May 15, 2020
40e1f02
- Split most of the EspnowMeshBackend code into utility files and the…
aerlon May 15, 2020
595fb23
Merge branch 'master' into wifi_mesh_update_2.2
aerlon May 18, 2020
f059e57
- Use the new Crypto, TypeConversion and random() functionality added…
aerlon May 18, 2020
0516b30
- Fix Readme links.
aerlon May 18, 2020
fba4ac1
- Make most type definitions public instead of protected, to facilita…
aerlon Jun 5, 2020
5661ec0
Merge branch 'master' into wifi_mesh_update_2.2
aerlon Jun 5, 2020
40b39f3
- Polish README.md.
aerlon Jun 5, 2020
1d2b6b5
- Make HelloMesh.ino stylish.
aerlon Jun 5, 2020
66138a6
- Add protected getters for _forwardingBacklog and _macIgnoreList in …
aerlon Jun 6, 2020
48281fb
- Correct terminology in README.md.
aerlon Jun 9, 2020
0662274
Merge branch 'master' into wifi_mesh_update_2.2
earlephilhower Jun 21, 2020
2ae3f6f
- Update README.md.
aerlon Jul 10, 2020
628298c
- Polish README.md.
aerlon Jul 12, 2020
7fbf620
Merge branch 'master' into wifi_mesh_update_2.2
devyte Mar 14, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
- Move all serialization code to separate Serializer namespace and fi…
…les.

- Generalize and improve JSON processing code.

- Prevent mesh passwords from containing " characters to avoid messing up the JSON processing.

- Improve documentation.
  • Loading branch information
aerlon committed May 10, 2020
commit 2ec2679d6eb55fc35d26a893b0a1e37a9da41170
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace TypeCast = MeshTypeConversionFunctions;
https://arduino-esp8266.readthedocs.io/en/latest/PROGMEM.html
*/
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.
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.
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.

// 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.
// All ESP-NOW keys below must match in an encrypted connection pair for encrypted communication to be possible.
Expand Down
2 changes: 1 addition & 1 deletion libraries/ESP8266WiFiMesh/examples/HelloMesh/HelloMesh.ino
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ namespace TypeCast = MeshTypeConversionFunctions;
https://arduino-esp8266.readthedocs.io/en/latest/PROGMEM.html
*/
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.
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.
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.

// 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.
// All ESP-NOW keys below must match in an encrypted connection pair for encrypted communication to be possible.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace TypeCast = MeshTypeConversionFunctions;
https://arduino-esp8266.readthedocs.io/en/latest/PROGMEM.html
*/
constexpr char exampleMeshName[] PROGMEM = "MeshNode_";
constexpr char exampleWiFiPassword[] PROGMEM = "ChangeThisWiFiPassword_TODO";
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.

unsigned int requestNumber = 0;
unsigned int responseNumber = 0;
Expand Down
13 changes: 3 additions & 10 deletions libraries/ESP8266WiFiMesh/src/EncryptedConnectionData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "TypeConversionFunctions.h"
#include "JsonTranslator.h"
#include "MeshCryptoInterface.h"
#include "Serializer.h"

namespace
{
Expand Down Expand Up @@ -157,16 +158,8 @@ bool EncryptedConnectionData::desync() const { return _desync; }

String EncryptedConnectionData::serialize() const
{
// Returns: {"connectionState":{"duration":"123","password":"abc","ownSK":"1A2","peerSK":"3B4","peerStaMac":"F2","peerApMac":"E3"}}

return
String(FPSTR(JsonTranslator::jsonConnectionState))
+ (temporary() ? String(FPSTR(JsonTranslator::jsonDuration)) + '\"' + String(temporary()->remainingDuration()) + F("\",") : emptyString)
+ FPSTR(JsonTranslator::jsonDesync) + '\"' + String(desync()) + F("\",")
+ FPSTR(JsonTranslator::jsonOwnSessionKey) + '\"' + TypeCast::uint64ToString(getOwnSessionKey()) + F("\",")
+ FPSTR(JsonTranslator::jsonPeerSessionKey) + '\"' + TypeCast::uint64ToString(getPeerSessionKey()) + F("\",")
+ FPSTR(JsonTranslator::jsonPeerStaMac) + '\"' + TypeCast::macToString(_peerStaMac) + F("\",")
+ FPSTR(JsonTranslator::jsonPeerApMac) + '\"' + TypeCast::macToString(_peerApMac) + F("\"}}");
return Serializer:: serializeEncryptedConnection((temporary() ? String(temporary()->remainingDuration()) : emptyString), String(desync()), TypeCast::uint64ToString(getOwnSessionKey()),
TypeCast::uint64ToString(getPeerSessionKey()), TypeCast::macToString(_peerStaMac), TypeCast::macToString(_peerApMac));
}

const ExpiringTimeTracker *EncryptedConnectionData::temporary() const
Expand Down
26 changes: 12 additions & 14 deletions libraries/ESP8266WiFiMesh/src/EspnowMeshBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ extern "C" {
#include "MutexTracker.h"
#include "JsonTranslator.h"
#include "MeshCryptoInterface.h"
#include "EspnowUtility.h"
#include "Serializer.h"

namespace
{
Expand Down Expand Up @@ -1112,7 +1114,7 @@ TransmissionStatusType EspnowMeshBackend::espnowSendToNode(const String &message
TransmissionStatusType EspnowMeshBackend::espnowSendToNodeUnsynchronized(const String message, const uint8_t *targetBSSID, const char messageType, const uint64_t messageID, EspnowMeshBackend *espnowInstance)
{
using namespace EspnowProtocolInterpreter;

MutexTracker mutexTracker(_espnowSendToNodeMutex);
if(!mutexTracker.mutexCaptured())
{
Expand Down Expand Up @@ -1773,7 +1775,7 @@ EncryptedConnectionStatus EspnowMeshBackend::requestEncryptedConnectionKernel(co
requestMessage = encryptionRequestBuilder(requestNonce, existingTimeTracker);
else if(_ongoingPeerRequestResult == EncryptedConnectionStatus::SOFT_LIMIT_CONNECTION_ESTABLISHED)
// We will only get a soft limit connection. Adjust future actions based on this.
requestMessage = JsonTranslator::createEncryptionRequestHmacMessage(FPSTR(temporaryEncryptionRequestHeader), requestNonce, getEspnowHashKey(),
requestMessage = Serializer::createEncryptionRequestHmacMessage(FPSTR(temporaryEncryptionRequestHeader), requestNonce, getEspnowHashKey(),
hashKeyLength, getAutoEncryptionDuration());
else
assert(false && String(F("Unknown _ongoingPeerRequestResult during encrypted connection finalization!")));
Expand Down Expand Up @@ -1848,7 +1850,7 @@ String EspnowMeshBackend::defaultEncryptionRequestBuilder(const String &requestH
{
(void)existingTimeTracker; // This removes a "unused parameter" compiler warning. Does nothing else.

return JsonTranslator::createEncryptionRequestHmacMessage(requestHeader, requestNonce, hashKey, hashKeyLength, durationMs);
return Serializer::createEncryptionRequestHmacMessage(requestHeader, requestNonce, hashKey, hashKeyLength, durationMs);
}

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

return createEncryptionRequestHmacMessage(FPSTR(temporaryEncryptionRequestHeader), requestNonce, hashKey, hashKeyLength, connectionDuration);
return Serializer::createEncryptionRequestHmacMessage(FPSTR(temporaryEncryptionRequestHeader), requestNonce, hashKey, hashKeyLength, connectionDuration);
}

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

confirmationsIterator = peerRequestConfirmationsToSend.erase(confirmationsIterator);
}
else if(espnowSendToNodeUnsynchronized(JsonTranslator::createEncryptionRequestHmacMessage(FPSTR(basicConnectionInfoHeader),
else if(espnowSendToNodeUnsynchronized(Serializer::createEncryptionRequestHmacMessage(FPSTR(basicConnectionInfoHeader),
confirmationsIterator->getPeerRequestNonce(), hashKey, hashKeyLength),
sendToDefaultBSSID ? defaultBSSID : unencryptedBSSID, 'C', generateMessageID(nullptr)) // Generates a new message ID to avoid sending encrypted sessionKeys over unencrypted connections.
== TransmissionStatusType::TRANSMISSION_COMPLETE)
Expand Down Expand Up @@ -2475,7 +2477,7 @@ void EspnowMeshBackend::sendPeerRequestConfirmations(const ExpiringTimeTracker *
if(!existingEncryptedConnection)
{
// Send "node full" message
espnowSendToNodeUnsynchronized(JsonTranslator::createEncryptionRequestHmacMessage(FPSTR(maxConnectionsReachedHeader),
espnowSendToNodeUnsynchronized(Serializer::createEncryptionRequestHmacMessage(FPSTR(maxConnectionsReachedHeader),
confirmationsIterator->getPeerRequestNonce(), hashKey, hashKeyLength),
defaultBSSID, 'C', generateMessageID(nullptr)); // Generates a new message ID to avoid sending encrypted sessionKeys over unencrypted connections.
}
Expand Down Expand Up @@ -2503,7 +2505,7 @@ void EspnowMeshBackend::sendPeerRequestConfirmations(const ExpiringTimeTracker *

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

String EspnowMeshBackend::serializeUnencryptedConnection()
{
using namespace JsonTranslator;

// Returns: {"connectionState":{"unsyncMsgID":"123"}}

return String(FPSTR(jsonConnectionState)) + createJsonEndPair(FPSTR(jsonUnsynchronizedMessageID), String(_unsynchronizedMessageID));
{
return Serializer::serializeUnencryptedConnection(String(_unsynchronizedMessageID));
}

String EspnowMeshBackend::serializeEncryptedConnection(const uint8_t *peerMac)
Expand Down
6 changes: 3 additions & 3 deletions libraries/ESP8266WiFiMesh/src/EspnowMeshBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -657,11 +657,11 @@ class EspnowMeshBackend : public MeshBackendBase {
* @param intervalMs The time to wait for an ack after having made an ESP-NOW transmission, in milliseconds. Defaults to 15 ms.
*/
static void setEspnowRetransmissionInterval(const uint32_t intervalMs);
static uint32_t getEspnowRetransmissionInterval();
static uint32_t getEspnowRetransmissionInterval();

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

void setAutoEncryptionDuration(const uint32_t duration);
uint32_t getAutoEncryptionDuration() const;
Expand Down Expand Up @@ -1217,7 +1217,7 @@ class EspnowMeshBackend : public MeshBackendBase {
* @param peerMac The MAC of the node with which an encrypted connection should be established.
* @param encryptionRequestBuilder A function which is responsible for constructing the request message to send.
* Called twice when the request is successful. First to build the initial request message and then to build the connection verification message.
* The request message should typically be of the form: JsonTranslator::createEncryptionRequestIntro() + JsonTranslator::createEncryptionRequestEnding().
* The request message should typically be of the form found in Serializer::createEncryptionRequestHmacMessage.
* @return The ultimate status of the requested encrypted connection, as EncryptedConnectionStatus.
*/
EncryptedConnectionStatus requestEncryptedConnectionKernel(const uint8_t *peerMac, const encryptionRequestBuilderType &encryptionRequestBuilder);
Expand Down
12 changes: 4 additions & 8 deletions libraries/ESP8266WiFiMesh/src/FloodingMesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "FloodingMesh.h"
#include "TypeConversionFunctions.h"
#include "JsonTranslator.h"
#include "Serializer.h"

namespace
{
Expand Down Expand Up @@ -153,16 +154,11 @@ void FloodingMesh::performMeshInstanceMaintenance()

String FloodingMesh::serializeMeshState() const
{
using namespace JsonTranslator;

// Returns: {"meshState":{"connectionState":{"unsyncMsgID":"123"},"meshMsgCount":"123"}}

String connectionState = getEspnowMeshBackendConst().serializeUnencryptedConnection();
uint32_t unsyncMsgID = 0;
JsonTranslator::getUnsynchronizedMessageID(connectionState, unsyncMsgID);

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

void FloodingMesh::loadMeshState(const String &serializedMeshState)
Expand Down
Loading