mirror of
https://github.com/thooge/esp32-nmea2000-obp60.git
synced 2026-08-18 18:32:30 +02:00
Only decompress zip after a succsessfully contenet download
This commit is contained in:
@@ -105,7 +105,6 @@ bool NetworkClient::httpGetGzip(const String& url, uint8_t*& outData, size_t& ou
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
|
||||||
if (DEBUGING) {
|
if (DEBUGING) {
|
||||||
String ce = http.header("Content-Encoding");
|
String ce = http.header("Content-Encoding");
|
||||||
String te = http.header("Transfer-Encoding");
|
String te = http.header("Transfer-Encoding");
|
||||||
@@ -132,9 +131,18 @@ bool NetworkClient::httpGetGzip(const String& url, uint8_t*& outData, size_t& ou
|
|||||||
String ce = http.header("Content-Encoding");
|
String ce = http.header("Content-Encoding");
|
||||||
bool isGzip = ce.equalsIgnoreCase("gzip");
|
bool isGzip = ce.equalsIgnoreCase("gzip");
|
||||||
|
|
||||||
|
// NEW: read expected body size if provided by server (prevents waiting forever for missing bytes)
|
||||||
|
int total = http.getSize(); // returns Content-Length, or -1 if unknown/chunked
|
||||||
|
|
||||||
|
// NEW: fail fast if server claims something larger than our buffer
|
||||||
|
if (total > 0 && (size_t)total > capacity) {
|
||||||
|
Serial.println("Response exceeds READLIMIT.");
|
||||||
|
aborting = true;
|
||||||
|
}
|
||||||
|
|
||||||
// NEW: if not gzip, we will not try to decompress (prevents false "Decompress OK" / random success)
|
// NEW: if not gzip, we will not try to decompress (prevents false "Decompress OK" / random success)
|
||||||
// You can either handle plain JSON here or just fail-fast.
|
// You can either handle plain JSON here or just fail-fast.
|
||||||
if (!isGzip) {
|
if (!isGzip && !aborting) {
|
||||||
if (DEBUGING) {
|
if (DEBUGING) {
|
||||||
Serial.println("Server response is NOT gzip (Content-Encoding != gzip).");
|
Serial.println("Server response is NOT gzip (Content-Encoding != gzip).");
|
||||||
Serial.println("Either disable Accept-Encoding: gzip or add plain-body handling here.");
|
Serial.println("Either disable Accept-Encoding: gzip or add plain-body handling here.");
|
||||||
@@ -142,7 +150,6 @@ bool NetworkClient::httpGetGzip(const String& url, uint8_t*& outData, size_t& ou
|
|||||||
|
|
||||||
// --- Plain-body handling (recommended): read full body into outData as-is ---
|
// --- Plain-body handling (recommended): read full body into outData as-is ---
|
||||||
// NEW: try to read Content-Length bytes if available (more robust)
|
// NEW: try to read Content-Length bytes if available (more robust)
|
||||||
int total = http.getSize(); // returns Content-Length, or -1 if unknown/chunked
|
|
||||||
if (total > 0 && (size_t)total > capacity) {
|
if (total > 0 && (size_t)total > capacity) {
|
||||||
Serial.println("Plain response exceeds READLIMIT.");
|
Serial.println("Plain response exceeds READLIMIT.");
|
||||||
aborting = true;
|
aborting = true;
|
||||||
@@ -175,6 +182,7 @@ bool NetworkClient::httpGetGzip(const String& url, uint8_t*& outData, size_t& ou
|
|||||||
lastData = millis();
|
lastData = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NEW: stop reading as soon as we have the full response
|
||||||
if (total > 0 && (int)len >= total) {
|
if (total > 0 && (int)len >= total) {
|
||||||
break; // we got full body
|
break; // we got full body
|
||||||
}
|
}
|
||||||
@@ -208,69 +216,94 @@ bool NetworkClient::httpGetGzip(const String& url, uint8_t*& outData, size_t& ou
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --- GZIP path (only if Content-Encoding is gzip) ---
|
// --- GZIP path (only if Content-Encoding is gzip) ---
|
||||||
while ((http.connected() || (stream && stream->available())) && !complete) {
|
if (!aborting) {
|
||||||
|
|
||||||
size_t avail = stream ? stream->available() : 0;
|
// NEW: read exactly Content-Length bytes when available (prevents partial-body timeout loops)
|
||||||
|
while ((http.connected() || (stream && stream->available())) && !complete && !aborting) {
|
||||||
|
|
||||||
if (avail == 0) {
|
size_t avail = stream ? stream->available() : 0;
|
||||||
if (millis() - lastData > READ_TIMEOUT) {
|
|
||||||
Serial.println("TIMEOUT waiting for data!");
|
if (avail == 0) {
|
||||||
aborting = true; // NEW: mark abnormal exit
|
// NEW: if Content-Length is known and we already read it all, stop immediately
|
||||||
|
if (total > 0 && (int)len >= total) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (millis() - lastData > READ_TIMEOUT) {
|
||||||
|
if (DEBUGING) {Serial.println("TIMEOUT waiting for data!");}
|
||||||
|
aborting = true; // NEW: mark abnormal exit
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
delay(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NEW: safety check if buffer limit is reached
|
||||||
|
if (len >= capacity) {
|
||||||
|
Serial.println("READLIMIT reached, aborting.");
|
||||||
|
aborting = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NEW: if Content-Length is known, do not read beyond it
|
||||||
|
if (total > 0) {
|
||||||
|
size_t remaining = (size_t)total - len;
|
||||||
|
if (avail > remaining) avail = remaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len + avail > capacity)
|
||||||
|
avail = capacity - len;
|
||||||
|
|
||||||
|
int read = stream->readBytes(buffer + len, avail);
|
||||||
|
if (read <= 0) {
|
||||||
|
// NEW: avoid tight loop if read returns zero
|
||||||
|
delay(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
len += (size_t)read;
|
||||||
|
lastData = millis();
|
||||||
|
|
||||||
|
if (DEBUGING) {Serial.printf("Read chunk: %d (total: %d)\n", read, (int)len);}
|
||||||
|
|
||||||
|
// NEW: if Content-Length is known and fully received, we can stop reading
|
||||||
|
if (total > 0 && (int)len >= total) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
delay(1);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NEW: safety check if buffer limit is reached
|
// NEW: only attempt gzip parse/decompress after we have a complete body (when Content-Length is known)
|
||||||
if (len >= capacity) {
|
// This avoids wasting heap with repeated malloc/free and reduces fragmentation over long runtimes.
|
||||||
Serial.println("READLIMIT reached, aborting.");
|
if (!aborting) {
|
||||||
aborting = true;
|
if (len < 20) {
|
||||||
break;
|
aborting = true;
|
||||||
|
} else {
|
||||||
|
int headerOffset = skipGzipHeader(buffer, len);
|
||||||
|
if (headerOffset < 0) {
|
||||||
|
aborting = true;
|
||||||
|
} else {
|
||||||
|
unsigned long testLen = len * 8; // Dynamic expansion
|
||||||
|
uint8_t* test = (uint8_t*)malloc(testLen);
|
||||||
|
|
||||||
|
if (!test) {
|
||||||
|
Serial.println("Malloc failed test buffer, aborting.");
|
||||||
|
aborting = true;
|
||||||
|
} else {
|
||||||
|
unsigned long srcLen = (unsigned long)(len - (size_t)headerOffset);
|
||||||
|
int res = puff(test, &testLen, buffer + headerOffset, &srcLen);
|
||||||
|
|
||||||
|
if (res == 0) {
|
||||||
|
if (DEBUGING) {Serial.printf("Decompress OK! Size: %lu bytes\n", testLen);}
|
||||||
|
outData = test;
|
||||||
|
outLen = (size_t)testLen;
|
||||||
|
complete = true;
|
||||||
|
} else {
|
||||||
|
free(test);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len + avail > capacity)
|
|
||||||
avail = capacity - len;
|
|
||||||
|
|
||||||
int read = stream->readBytes(buffer + len, avail);
|
|
||||||
if (read <= 0) {
|
|
||||||
// NEW: avoid tight loop if read returns zero
|
|
||||||
delay(1);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
len += (size_t)read;
|
|
||||||
lastData = millis();
|
|
||||||
|
|
||||||
if (DEBUGING) {Serial.printf("Read chunk: %d (total: %d)\n", read, (int)len);}
|
|
||||||
|
|
||||||
if (len < 20) continue; // Not enough data for header
|
|
||||||
|
|
||||||
int headerOffset = skipGzipHeader(buffer, len);
|
|
||||||
if (headerOffset < 0) continue;
|
|
||||||
|
|
||||||
unsigned long testLen = len * 8; // Dynamic expansion
|
|
||||||
uint8_t* test = (uint8_t*)malloc(testLen);
|
|
||||||
|
|
||||||
if (!test) {
|
|
||||||
// NEW: abort if allocation fails to prevent endless retry loop
|
|
||||||
Serial.println("Malloc failed test buffer, aborting.");
|
|
||||||
aborting = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long srcLen = len - headerOffset;
|
|
||||||
|
|
||||||
int res = puff(test, &testLen, buffer + headerOffset, &srcLen);
|
|
||||||
if (res == 0) {
|
|
||||||
if (DEBUGING) {Serial.printf("Decompress OK! Size: %lu bytes\n", testLen);}
|
|
||||||
outData = test;
|
|
||||||
outLen = (size_t)testLen;
|
|
||||||
complete = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(test);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Added: Force-close connection only if aborted to avoid TCP RST storms ---
|
// --- Added: Force-close connection only if aborted to avoid TCP RST storms ---
|
||||||
|
|||||||
Reference in New Issue
Block a user