@alteriom/painlessmesh 2.0.1 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +145 -0
- package/CONTRIBUTING.md +15 -0
- package/README.md +6 -2
- package/RELEASE_GUIDE.md +27 -5
- package/examples/sendToInternet/README.md +3 -3
- package/examples/sendToInternet/sendToInternet.ino +58 -23
- package/library.json +1 -1
- package/library.properties +1 -1
- package/package.json +1 -1
- package/src/AlteriomPainlessMesh.h +2 -2
- package/src/arduino/wifi.hpp +178 -77
- package/src/painlessmesh/callback.hpp +7 -0
- package/src/painlessmesh/gateway.hpp +335 -7
- package/src/painlessmesh/logger.hpp +14 -1
- package/src/painlessmesh/mesh.hpp +232 -20
- package/src/painlessmesh/router.hpp +17 -7
|
@@ -98,6 +98,9 @@ struct PendingInternetRequest {
|
|
|
98
98
|
TSTRING destination = ""; ///< Internet destination URL
|
|
99
99
|
TSTRING payload = ""; ///< Request payload
|
|
100
100
|
internetResultCallback_t callback; ///< User callback for result
|
|
101
|
+
/// Why the last attempt failed, when retries were spent waiting for a
|
|
102
|
+
/// gateway; the final callback reports it instead of a bare retry count.
|
|
103
|
+
TSTRING lastError = "";
|
|
101
104
|
|
|
102
105
|
/**
|
|
103
106
|
* Check if this request has timed out
|
|
@@ -243,6 +246,37 @@ class Mesh : public ntp::MeshTime, public plugin::PackageHandler<T> {
|
|
|
243
246
|
painlessmesh::ntp::addPackageCallback(this->callbackList, (*this));
|
|
244
247
|
painlessmesh::router::addPackageCallback(this->callbackList, (*this));
|
|
245
248
|
|
|
249
|
+
// Every node answers a gateway request it cannot serve. A bridge that
|
|
250
|
+
// reboots, crashes or is reflashed as a regular node announces nothing
|
|
251
|
+
// -- only a bridge stepping down in-process sends `leaving` -- so its
|
|
252
|
+
// peers keep it in knownBridges until its last status ages out
|
|
253
|
+
// (bridgeTimeoutMs, 60 s) and may route every Internet request to it.
|
|
254
|
+
// A regular node had no GATEWAY_DATA handler and dropped them without a
|
|
255
|
+
// word; the origin waited out its request timeout, 30 s, each time.
|
|
256
|
+
// Found on the HIL rig while validating 2.0.3.
|
|
257
|
+
//
|
|
258
|
+
// Registered first, so a gateway's own handler (initGatewayInternetHandler
|
|
259
|
+
// in wifi.hpp, or a test's stand-in) is always the second: this one
|
|
260
|
+
// stays silent whenever any other GATEWAY_DATA handler exists.
|
|
261
|
+
this->callbackList.onPackage(
|
|
262
|
+
protocol::GATEWAY_DATA,
|
|
263
|
+
[this](protocol::Variant& variant, std::shared_ptr<T> ingress,
|
|
264
|
+
uint32_t) {
|
|
265
|
+
if (this->callbackList.count(protocol::GATEWAY_DATA) > 1) {
|
|
266
|
+
return false; // this node is a gateway; its handler answers
|
|
267
|
+
}
|
|
268
|
+
auto pkg = variant.to<gateway::GatewayDataPackage>();
|
|
269
|
+
char errorBuf[96];
|
|
270
|
+
snprintf(errorBuf, sizeof(errorBuf), "Node %u %s",
|
|
271
|
+
static_cast<unsigned>(this->nodeId),
|
|
272
|
+
gateway::GATEWAY_NOT_A_GATEWAY_PHRASE);
|
|
273
|
+
Log(logger::ERROR,
|
|
274
|
+
"GATEWAY_DATA from node %u answered: %s\n",
|
|
275
|
+
static_cast<unsigned>(pkg.originNode), errorBuf);
|
|
276
|
+
this->sendGatewayAck(pkg, false, 0, TSTRING(errorBuf), ingress);
|
|
277
|
+
return true;
|
|
278
|
+
});
|
|
279
|
+
|
|
246
280
|
// Seed delivery-confirmation ids with a random value so they do not
|
|
247
281
|
// restart at 1 after a reboot — a delayed ACK for a pre-reboot
|
|
248
282
|
// message could otherwise match a fresh message's id and report a
|
|
@@ -1349,7 +1383,8 @@ class Mesh : public ntp::MeshTime, public plugin::PackageHandler<T> {
|
|
|
1349
1383
|
|
|
1350
1384
|
size_t removed = sizeBefore - knownBridges.size();
|
|
1351
1385
|
if (removed > 0) {
|
|
1352
|
-
Log(GENERAL, "cleanupExpiredBridges(): Removed %
|
|
1386
|
+
Log(GENERAL, "cleanupExpiredBridges(): Removed %lu expired bridges\n",
|
|
1387
|
+
static_cast<unsigned long>(removed));
|
|
1353
1388
|
}
|
|
1354
1389
|
}
|
|
1355
1390
|
|
|
@@ -1432,6 +1467,31 @@ class Mesh : public ntp::MeshTime, public plugin::PackageHandler<T> {
|
|
|
1432
1467
|
return internetHealthChecker.hasLocalInternet();
|
|
1433
1468
|
}
|
|
1434
1469
|
|
|
1470
|
+
/**
|
|
1471
|
+
* Can this node serve a gateway request on its own uplink right now?
|
|
1472
|
+
*
|
|
1473
|
+
* hasLocalInternet() is the last periodic probe's answer. On a bridge the
|
|
1474
|
+
* first probe runs while the station is still associating and fails, and
|
|
1475
|
+
* the next is a full interval (30 s) away, so for that whole window a send
|
|
1476
|
+
* fell through to the mesh path and was refused for want of a peer (issue
|
|
1477
|
+
* #450). When the flag says no and the health check is running, spend the
|
|
1478
|
+
* one on-demand probe the checker allows per period: a send made after the
|
|
1479
|
+
* uplink came up is then served locally, and a node whose uplink really is
|
|
1480
|
+
* down pays one probe per interval, not one per call.
|
|
1481
|
+
*
|
|
1482
|
+
* @return true if the request should go to this node's own gateway handler
|
|
1483
|
+
*/
|
|
1484
|
+
bool uplinkServesLocally() {
|
|
1485
|
+
if (hasLocalInternet()) return true;
|
|
1486
|
+
if (!isInternetHealthCheckEnabled()) return false;
|
|
1487
|
+
if (internetHealthChecker.checkOnDemand()) {
|
|
1488
|
+
Log(logger::COMMUNICATION,
|
|
1489
|
+
"uplinkServesLocally(): on-demand probe found the uplink up\n");
|
|
1490
|
+
return true;
|
|
1491
|
+
}
|
|
1492
|
+
return false;
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1435
1495
|
/**
|
|
1436
1496
|
* Register callback for local Internet connectivity changes
|
|
1437
1497
|
*
|
|
@@ -1546,8 +1606,17 @@ class Mesh : public ntp::MeshTime, public plugin::PackageHandler<T> {
|
|
|
1546
1606
|
void enableInternetHealthCheck() {
|
|
1547
1607
|
using namespace logger;
|
|
1548
1608
|
if (internetHealthCheckTask != nullptr) {
|
|
1549
|
-
|
|
1550
|
-
|
|
1609
|
+
if (internetHealthCheckTask->isEnabled()) {
|
|
1610
|
+
Log(GENERAL, "enableInternetHealthCheck(): Already enabled\n");
|
|
1611
|
+
return;
|
|
1612
|
+
}
|
|
1613
|
+
// A stop()/re-init cycle -- what bridge promotion does before calling
|
|
1614
|
+
// initAsBridge() again -- disables every task and drops it from the
|
|
1615
|
+
// reusable pool, but this member still points at it. Refusing here
|
|
1616
|
+
// would leave a re-initialised node with no health check at all, and
|
|
1617
|
+
// so with hasLocalInternet() stuck false (issue #445). Re-arm instead,
|
|
1618
|
+
// releasing the spent task so the pool can reclaim it.
|
|
1619
|
+
internetHealthCheckTask = nullptr;
|
|
1551
1620
|
}
|
|
1552
1621
|
|
|
1553
1622
|
Log(GENERAL, "enableInternetHealthCheck(): Starting health check task (interval: %u ms)\n",
|
|
@@ -1663,7 +1732,7 @@ class Mesh : public ntp::MeshTime, public plugin::PackageHandler<T> {
|
|
|
1663
1732
|
// A shared gateway can execute its own gateway package locally. Keep the
|
|
1664
1733
|
// same package handler, pending-request tracking and callback semantics,
|
|
1665
1734
|
// but do not require a mesh peer merely to reach this node's own uplink.
|
|
1666
|
-
if (
|
|
1735
|
+
if (uplinkServesLocally()) {
|
|
1667
1736
|
PendingInternetRequest request;
|
|
1668
1737
|
request.messageId = messageId;
|
|
1669
1738
|
request.timestamp = millis();
|
|
@@ -1678,20 +1747,8 @@ class Mesh : public ntp::MeshTime, public plugin::PackageHandler<T> {
|
|
|
1678
1747
|
request.callback = callback;
|
|
1679
1748
|
pendingInternetRequests[messageId] = request;
|
|
1680
1749
|
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
pkg.dest = this->nodeId;
|
|
1684
|
-
pkg.messageId = messageId;
|
|
1685
|
-
pkg.originNode = this->nodeId;
|
|
1686
|
-
pkg.timestamp = this->getNodeTime();
|
|
1687
|
-
pkg.priority = priority;
|
|
1688
|
-
pkg.destination = destination;
|
|
1689
|
-
pkg.payload = payload;
|
|
1690
|
-
pkg.contentType = "application/json";
|
|
1691
|
-
pkg.retryCount = 0;
|
|
1692
|
-
pkg.requiresAck = true;
|
|
1693
|
-
protocol::Variant variant(&pkg);
|
|
1694
|
-
this->callbackList.execute(protocol::GATEWAY_DATA, variant, nullptr, 0);
|
|
1750
|
+
dispatchInternetRequestLocally(messageId, priority, 0, destination,
|
|
1751
|
+
payload);
|
|
1695
1752
|
return messageId;
|
|
1696
1753
|
}
|
|
1697
1754
|
|
|
@@ -1938,6 +1995,65 @@ class Mesh : public ntp::MeshTime, public plugin::PackageHandler<T> {
|
|
|
1938
1995
|
/**
|
|
1939
1996
|
* Handle incoming gateway acknowledgment package
|
|
1940
1997
|
*/
|
|
1998
|
+
public:
|
|
1999
|
+
// Public: the gateway handler in wifi.hpp, a derived class, answers with it.
|
|
2000
|
+
/**
|
|
2001
|
+
* Answer a gateway request: send its GATEWAY_ACK back to the origin node.
|
|
2002
|
+
*
|
|
2003
|
+
* A request this node originated completes locally, without a mesh hop.
|
|
2004
|
+
* Otherwise the ack is routed to the origin; when the NodeTree has not yet
|
|
2005
|
+
* converged enough for findRoute() to resolve it -- a freshly promoted
|
|
2006
|
+
* gateway can receive data before that -- the connection the request
|
|
2007
|
+
* arrived on is a valid reverse path, since every intermediate node routes
|
|
2008
|
+
* the addressed ack onward toward the origin.
|
|
2009
|
+
*
|
|
2010
|
+
* Used by the gateway's own handler (wifi.hpp) and by the fallback every
|
|
2011
|
+
* node registers for requests it cannot serve.
|
|
2012
|
+
*/
|
|
2013
|
+
void sendGatewayAck(const gateway::GatewayDataPackage& request, bool success,
|
|
2014
|
+
uint16_t httpStatus, const TSTRING& error,
|
|
2015
|
+
std::shared_ptr<T> ingressConnection = nullptr) {
|
|
2016
|
+
using namespace logger;
|
|
2017
|
+
|
|
2018
|
+
gateway::GatewayAckPackage ack;
|
|
2019
|
+
ack.from = this->nodeId;
|
|
2020
|
+
ack.dest = request.originNode;
|
|
2021
|
+
ack.messageId = request.messageId;
|
|
2022
|
+
ack.originNode = request.originNode;
|
|
2023
|
+
ack.success = success;
|
|
2024
|
+
ack.httpStatus = httpStatus;
|
|
2025
|
+
ack.error = error;
|
|
2026
|
+
ack.timestamp = this->getNodeTime();
|
|
2027
|
+
|
|
2028
|
+
if (request.originNode == this->nodeId) {
|
|
2029
|
+
protocol::Variant variant(&ack);
|
|
2030
|
+
this->callbackList.execute(protocol::GATEWAY_ACK, variant, nullptr, 0);
|
|
2031
|
+
Log(COMMUNICATION,
|
|
2032
|
+
"Completed local GATEWAY_ACK (success=%d, http=%d)\n", success,
|
|
2033
|
+
httpStatus);
|
|
2034
|
+
return;
|
|
2035
|
+
}
|
|
2036
|
+
|
|
2037
|
+
auto conn = router::findRoute<T>((*this), request.originNode);
|
|
2038
|
+
if (!conn && ingressConnection) {
|
|
2039
|
+
conn = ingressConnection;
|
|
2040
|
+
Log(COMMUNICATION,
|
|
2041
|
+
"Routing GATEWAY_ACK to node %u through request ingress while "
|
|
2042
|
+
"topology converges\n",
|
|
2043
|
+
request.originNode);
|
|
2044
|
+
}
|
|
2045
|
+
if (conn) {
|
|
2046
|
+
protocol::Variant variant(&ack);
|
|
2047
|
+
router::send(std::move(variant), conn);
|
|
2048
|
+
Log(COMMUNICATION, "Sent GATEWAY_ACK to node %u (success=%d, http=%d)\n",
|
|
2049
|
+
request.originNode, success, httpStatus);
|
|
2050
|
+
} else {
|
|
2051
|
+
Log(ERROR, "Failed to send GATEWAY_ACK: no route to node %u\n",
|
|
2052
|
+
request.originNode);
|
|
2053
|
+
}
|
|
2054
|
+
}
|
|
2055
|
+
|
|
2056
|
+
private:
|
|
1941
2057
|
void handleGatewayAck(const gateway::GatewayAckPackage& ack) {
|
|
1942
2058
|
using namespace logger;
|
|
1943
2059
|
Log(COMMUNICATION, "handleGatewayAck(): msgId=%u success=%d http=%u\n",
|
|
@@ -1961,6 +2077,46 @@ class Mesh : public ntp::MeshTime, public plugin::PackageHandler<T> {
|
|
|
1961
2077
|
return;
|
|
1962
2078
|
}
|
|
1963
2079
|
|
|
2080
|
+
// The node this request went to is not a gateway (issue found on the
|
|
2081
|
+
// HIL rig while validating 2.0.3): it rebooted or was reflashed as a
|
|
2082
|
+
// regular node without announcing it, and its last bridge status is
|
|
2083
|
+
// still inside bridgeTimeoutMs. Forget it and send again through the
|
|
2084
|
+
// next gateway at once. The retry budget is not spent: nothing was
|
|
2085
|
+
// attempted against the Internet, and every such answer removes one
|
|
2086
|
+
// entry from knownBridges, so this cannot loop.
|
|
2087
|
+
if (gateway::responseContains(ack.error,
|
|
2088
|
+
gateway::GATEWAY_NOT_A_GATEWAY_PHRASE)) {
|
|
2089
|
+
const uint32_t staleGateway = request.gatewayNodeId;
|
|
2090
|
+
bool forgot = this->forgetBridge(staleGateway);
|
|
2091
|
+
if (ack.from != staleGateway) forgot = this->forgetBridge(ack.from) || forgot;
|
|
2092
|
+
Log(ERROR, "handleGatewayAck(): %s; forgot it as a gateway for msgId=%u\n",
|
|
2093
|
+
ack.error.c_str(), ack.messageId);
|
|
2094
|
+
|
|
2095
|
+
if (!forgot) {
|
|
2096
|
+
// Nothing to forget, so a redispatch would reach the same node.
|
|
2097
|
+
// Fall through to the ordinary failure path below.
|
|
2098
|
+
} else if (this->getPrimaryBridge() == nullptr &&
|
|
2099
|
+
!this->uplinkServesLocally()) {
|
|
2100
|
+
// No gateway left right now. On the rig the live bridge's first
|
|
2101
|
+
// status arrived half a second after the ex-bridge answered, so an
|
|
2102
|
+
// accepted request rides the ordinary retry backoff rather than
|
|
2103
|
+
// failing on the spot; retryInternetRequest() reschedules while no
|
|
2104
|
+
// gateway is known, and the final callback carries this reason.
|
|
2105
|
+
char errorBuf[160];
|
|
2106
|
+
snprintf(errorBuf, sizeof(errorBuf),
|
|
2107
|
+
"No Internet gateway available: %s", ack.error.c_str());
|
|
2108
|
+
request.lastError = TSTRING(errorBuf);
|
|
2109
|
+
scheduleInternetRetry(ack.messageId);
|
|
2110
|
+
return;
|
|
2111
|
+
} else {
|
|
2112
|
+
const uint32_t messageId = ack.messageId;
|
|
2113
|
+
this->addTask([this, messageId]() {
|
|
2114
|
+
this->retryInternetRequest(messageId);
|
|
2115
|
+
});
|
|
2116
|
+
return;
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
|
|
1964
2120
|
// Failure response - determine if retryable
|
|
1965
2121
|
bool isRetryable = false;
|
|
1966
2122
|
|
|
@@ -2041,6 +2197,37 @@ class Mesh : public ntp::MeshTime, public plugin::PackageHandler<T> {
|
|
|
2041
2197
|
}
|
|
2042
2198
|
}
|
|
2043
2199
|
|
|
2200
|
+
/**
|
|
2201
|
+
* Run a gateway request against this node's own uplink
|
|
2202
|
+
*
|
|
2203
|
+
* The package goes to this node's own GATEWAY_DATA handler, so the
|
|
2204
|
+
* acknowledgment, pending-request tracking and callback semantics stay
|
|
2205
|
+
* identical to a request served by a peer gateway.
|
|
2206
|
+
*
|
|
2207
|
+
* The handler runs synchronously and its acknowledgment can erase the
|
|
2208
|
+
* pending entry, so callers must not hold a reference into
|
|
2209
|
+
* pendingInternetRequests across this call -- pass copies.
|
|
2210
|
+
*/
|
|
2211
|
+
void dispatchInternetRequestLocally(uint32_t messageId, uint8_t priority,
|
|
2212
|
+
uint8_t retryCount,
|
|
2213
|
+
const TSTRING& destination,
|
|
2214
|
+
const TSTRING& payload) {
|
|
2215
|
+
gateway::GatewayDataPackage pkg;
|
|
2216
|
+
pkg.from = this->nodeId;
|
|
2217
|
+
pkg.dest = this->nodeId;
|
|
2218
|
+
pkg.messageId = messageId;
|
|
2219
|
+
pkg.originNode = this->nodeId;
|
|
2220
|
+
pkg.timestamp = this->getNodeTime();
|
|
2221
|
+
pkg.priority = priority;
|
|
2222
|
+
pkg.destination = destination;
|
|
2223
|
+
pkg.payload = payload;
|
|
2224
|
+
pkg.contentType = "application/json";
|
|
2225
|
+
pkg.retryCount = retryCount;
|
|
2226
|
+
pkg.requiresAck = true;
|
|
2227
|
+
protocol::Variant variant(&pkg);
|
|
2228
|
+
this->callbackList.execute(protocol::GATEWAY_DATA, variant, nullptr, 0);
|
|
2229
|
+
}
|
|
2230
|
+
|
|
2044
2231
|
/**
|
|
2045
2232
|
* Schedule retry for a failed Internet request
|
|
2046
2233
|
*/
|
|
@@ -2053,11 +2240,14 @@ class Mesh : public ntp::MeshTime, public plugin::PackageHandler<T> {
|
|
|
2053
2240
|
PendingInternetRequest& request = it->second;
|
|
2054
2241
|
|
|
2055
2242
|
if (request.retryCount >= request.maxRetries) {
|
|
2056
|
-
// Max retries reached - fail the request
|
|
2243
|
+
// Max retries reached - fail the request, with the reason the retries
|
|
2244
|
+
// were spent on when there is one
|
|
2057
2245
|
Log(logger::ERROR, "scheduleInternetRetry(): Max retries reached for msgId=%u\n",
|
|
2058
2246
|
messageId);
|
|
2059
2247
|
if (request.callback) {
|
|
2060
|
-
request.callback(false, 0,
|
|
2248
|
+
request.callback(false, 0,
|
|
2249
|
+
request.lastError.length() > 0 ? request.lastError
|
|
2250
|
+
: TSTRING("Max retries exceeded"));
|
|
2061
2251
|
}
|
|
2062
2252
|
pendingInternetRequests.erase(it);
|
|
2063
2253
|
return;
|
|
@@ -2087,6 +2277,28 @@ class Mesh : public ntp::MeshTime, public plugin::PackageHandler<T> {
|
|
|
2087
2277
|
|
|
2088
2278
|
PendingInternetRequest& request = it->second;
|
|
2089
2279
|
|
|
2280
|
+
// A request this node is serving from its own uplink never had a mesh
|
|
2281
|
+
// hop to repeat. The routing path below needs an active peer and a
|
|
2282
|
+
// discovered bridge, so a lone gateway would burn every retry without
|
|
2283
|
+
// issuing a single HTTP request and then report "Max retries exceeded"
|
|
2284
|
+
// in place of the transport error that actually occurred -- the same
|
|
2285
|
+
// dishonest failure issue #446 was about.
|
|
2286
|
+
//
|
|
2287
|
+
// Copy what the redispatch needs first: the local handler runs
|
|
2288
|
+
// synchronously and can erase this entry, leaving `request` dangling.
|
|
2289
|
+
if (request.gatewayNodeId == this->nodeId && uplinkServesLocally()) {
|
|
2290
|
+
const uint8_t priority = request.priority;
|
|
2291
|
+
const uint8_t retryCount = request.retryCount;
|
|
2292
|
+
const TSTRING destination = request.destination;
|
|
2293
|
+
const TSTRING payload = request.payload;
|
|
2294
|
+
Log(logger::COMMUNICATION,
|
|
2295
|
+
"retryInternetRequest(): Retrying msgId=%u on the local uplink\n",
|
|
2296
|
+
messageId);
|
|
2297
|
+
dispatchInternetRequestLocally(messageId, priority, retryCount,
|
|
2298
|
+
destination, payload);
|
|
2299
|
+
return;
|
|
2300
|
+
}
|
|
2301
|
+
|
|
2090
2302
|
// Check mesh connectivity before attempting retry
|
|
2091
2303
|
// During bridge failover, connection may be temporarily lost
|
|
2092
2304
|
if (!hasActiveMeshConnections()) {
|
|
@@ -204,9 +204,14 @@ void routePackage(const layout::Layout<T>& layout,
|
|
|
204
204
|
#if ARDUINOJSON_VERSION_MAJOR == 7
|
|
205
205
|
protocol::Variant variant(pkg);
|
|
206
206
|
if (variant.error) {
|
|
207
|
+
// The error is a DeserializationError object, not an integer: passing it
|
|
208
|
+
// through varargs is undefined behaviour. size_t is unsigned long on the
|
|
209
|
+
// 64-bit desktop build and unsigned int on ESP32/ESP8266, so it is cast
|
|
210
|
+
// to one type and printed with the matching specifier.
|
|
207
211
|
Log(ERROR,
|
|
208
|
-
"routePackage(): parsing failed. err=%
|
|
209
|
-
variant.error
|
|
212
|
+
"routePackage(): parsing failed. err=%s, total_length=%lu, data=%s<--\n",
|
|
213
|
+
variant.error.c_str(), static_cast<unsigned long>(pkg.length()),
|
|
214
|
+
pkg.c_str());
|
|
210
215
|
return;
|
|
211
216
|
}
|
|
212
217
|
|
|
@@ -248,15 +253,20 @@ void routePackage(const layout::Layout<T>& layout,
|
|
|
248
253
|
auto variant = std::make_shared<protocol::Variant>(pkg, capacity);
|
|
249
254
|
|
|
250
255
|
if (variant->error) {
|
|
256
|
+
// Same two defects as the ArduinoJson 7 branch above (CodeQL
|
|
257
|
+
// cpp/wrong-type-format-argument, alerts #6-#9).
|
|
251
258
|
if (variant->error == DeserializationError::NoMemory) {
|
|
252
259
|
Log(ERROR,
|
|
253
|
-
"routePackage(): Message too large. length=%
|
|
254
|
-
"nesting_depth=%
|
|
255
|
-
pkg.length(),
|
|
260
|
+
"routePackage(): Message too large. length=%lu, calculated_capacity=%lu, "
|
|
261
|
+
"nesting_depth=%lu. Consider increasing MAX_MESSAGE_CAPACITY if needed.\n",
|
|
262
|
+
static_cast<unsigned long>(pkg.length()),
|
|
263
|
+
static_cast<unsigned long>(calculatedCapacity),
|
|
264
|
+
static_cast<unsigned long>(nestingDepth));
|
|
256
265
|
} else {
|
|
257
266
|
Log(ERROR,
|
|
258
|
-
"routePackage(): parsing failed. err=%
|
|
259
|
-
variant->error
|
|
267
|
+
"routePackage(): parsing failed. err=%s, length=%lu, data=%s<--\n",
|
|
268
|
+
variant->error.c_str(), static_cast<unsigned long>(pkg.length()),
|
|
269
|
+
pkg.c_str());
|
|
260
270
|
}
|
|
261
271
|
return;
|
|
262
272
|
}
|