Check for incomplete downloads before saving

Downloads should only fail like this is if your WiFi signal is poor, your internet connection is awful or the server is experiencing issues.
This commit is contained in:
wiidev 2020-04-14 21:40:38 +01:00
parent 750614e055
commit 4da7f23e9a

View File

@ -103,7 +103,7 @@ u8 is_chunked(struct phr_header *headers, size_t num_headers)
return (strcasecmp(encoding, "chunked") == 0) ? 1 : 0; return (strcasecmp(encoding, "chunked") == 0) ? 1 : 0;
} }
void read_chunked(HTTP_INFO *httpinfo, struct download *buffer, size_t start_pos) u8 read_chunked(HTTP_INFO *httpinfo, struct download *buffer, size_t start_pos)
{ {
struct phr_chunked_decoder decoder = {}; struct phr_chunked_decoder decoder = {};
size_t capacity = 4096, rsize; size_t capacity = 4096, rsize;
@ -129,7 +129,7 @@ void read_chunked(HTTP_INFO *httpinfo, struct download *buffer, size_t start_pos
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("IO error\n"); gprintf("IO error\n");
#endif #endif
return; return 0;
} }
rsize = rret; rsize = rret;
pret = phr_decode_chunked(&decoder, &buffer->data[start_pos], &rsize); pret = phr_decode_chunked(&decoder, &buffer->data[start_pos], &rsize);
@ -138,15 +138,16 @@ void read_chunked(HTTP_INFO *httpinfo, struct download *buffer, size_t start_pos
#ifdef DEBUG_NETWORK #ifdef DEBUG_NETWORK
gprintf("Parse error\n"); gprintf("Parse error\n");
#endif #endif
return; return 0;
} }
start_pos += rsize; start_pos += rsize;
} while (pret == -2); } while (pret == -2);
buffer->size = start_pos; buffer->size = start_pos;
buffer->data = MEM2_realloc(buffer->data, buffer->size); buffer->data = MEM2_realloc(buffer->data, buffer->size);
return 1;
} }
void read_all(HTTP_INFO *httpinfo, struct download *buffer, size_t start_pos) u8 read_all(HTTP_INFO *httpinfo, struct download *buffer, size_t start_pos)
{ {
size_t capacity = 4096; size_t capacity = 4096;
ssize_t ret; ssize_t ret;
@ -165,13 +166,16 @@ void read_all(HTTP_INFO *httpinfo, struct download *buffer, size_t start_pos)
} }
while ((ret = https_read(httpinfo, &buffer->data[start_pos], capacity - start_pos)) == -1 && errno == EINTR) while ((ret = https_read(httpinfo, &buffer->data[start_pos], capacity - start_pos)) == -1 && errno == EINTR)
; ;
if (ret <= 0) if (ret == 0)
break; break;
if (ret < 0)
return 0;
start_pos += ret; start_pos += ret;
}; };
buffer->size = start_pos; buffer->size = start_pos;
buffer->data = MEM2_realloc(buffer->data, buffer->size); buffer->data = MEM2_realloc(buffer->data, buffer->size);
return 1;
} }
int connect(char *host, u16 port) int connect(char *host, u16 port)
@ -383,7 +387,7 @@ void downloadfile(const char *url, struct download *buffer)
// Get the response // Get the response
char response[4096]; char response[4096];
struct phr_header headers[100]; struct phr_header headers[100];
int pret, minor_version, status; int pret, minor_version, status, dl_valid;
size_t buflen = 0, prevbuflen = 0, num_headers, msg_len; size_t buflen = 0, prevbuflen = 0, num_headers, msg_len;
ssize_t rret; ssize_t rret;
const char *msg; const char *msg;
@ -454,13 +458,23 @@ void downloadfile(const char *url, struct download *buffer)
if (status == 200) if (status == 200)
{ {
buffer->data = MEM2_alloc(4096); buffer->data = MEM2_alloc(4096);
buffer->size = 4096;
memcpy(buffer->data, &response[pret], buflen - pret); memcpy(buffer->data, &response[pret], buflen - pret);
// Determine how to read the data // Determine how to read the data
if (is_chunked(headers, num_headers)) if (is_chunked(headers, num_headers))
read_chunked(&httpinfo, buffer, buflen - pret); dl_valid = read_chunked(&httpinfo, buffer, buflen - pret);
else else
read_all(&httpinfo, buffer, buflen - pret); dl_valid = read_all(&httpinfo, buffer, buflen - pret);
// Check if the download is incomplete
if (!dl_valid || buffer->size <= 0)
{
buffer->size = 0;
MEM2_free(buffer->data);
#ifdef DEBUG_NETWORK
gprintf("Removed incomplete download\n");
#endif
https_close(&httpinfo);
return;
}
// Save the session // Save the session
if (httpinfo.use_https) if (httpinfo.use_https)
session = wolfSSL_get_session(httpinfo.ssl); session = wolfSSL_get_session(httpinfo.ssl);