naett.c

Tiny cross-platform HTTP / HTTPS client library in C.
git clone git://git.finwo.net/lib/naett.c
Log | Files | Refs | README | LICENSE

commit 864c851839ab5667ecc39f1633c407e35b649b8a
parent 333252b443356f2bb9733ea2656a09c66d2fd203
Author: Henrik RydgÄrd <hrydgard@gmail.com>
Date:   Fri, 21 Jul 2023 17:38:51 +0200

Add naettGetTotalBytesRead, for reading download progress safely

Diffstat:
Mnaett.h | 7+++++++
Msrc/naett_android.c | 11+++++++++--
Msrc/naett_core.c | 9+++++++++
Msrc/naett_internal.h | 2++
Msrc/naett_linux.c | 1+
Msrc/naett_osx.c | 7+++++++
Msrc/naett_win.c | 7++++++-
7 files changed, 41 insertions(+), 3 deletions(-)

diff --git a/naett.h b/naett.h @@ -112,6 +112,13 @@ const void* naettGetBody(naettRes* response, int* outSize); const char* naettGetHeader(naettRes* response, const char* name); /** + * @brief Returns how many bytes have been read from the response so far, + * and the integer pointed to by totalSize gets the Content-Length if available, + * or -1 if not (or 0 if headers have not been read yet). + */ +int naettGetTotalBytesRead(naettRes* response, int* totalSize); + +/** * @brief Enumerates all response headers as long as the `lister` * returns true. */ diff --git a/src/naett_android.c b/src/naett_android.c @@ -198,6 +198,11 @@ static void* processRequest(void* data) { } res->headers = firstHeader; + const char *contentLength = naettGetHeader((naettRes *)res, "Content-Length"); + if (!contentLength || sscanf(contentLength, "%d", &res->contentLength) != 1) { + res->contentLength = -1; + } + int statusCode = intCall(env, connection, "getResponseCode", "()I"); jobject inputStream = NULL; @@ -221,9 +226,11 @@ static void* processRequest(void* data) { } if (bytesRead < 0) { break; + } else if (bytesRead > 0) { + (*env)->GetByteArrayRegion(env, buffer, 0, bytesRead, (jbyte*) byteBuffer); + req->options.bodyWriter(byteBuffer, bytesRead, req->options.bodyWriterData); + res->totalBytesRead += bytesRead; } - (*env)->GetByteArrayRegion(env, buffer, 0, bytesRead, (jbyte*) byteBuffer); - req->options.bodyWriter(byteBuffer, bytesRead, req->options.bodyWriterData); } while (!res->closeRequested); voidCall(env, inputStream, "close", "()V"); diff --git a/src/naett_core.c b/src/naett_core.c @@ -314,6 +314,15 @@ const void* naettGetBody(naettRes* response, int* size) { return res->body.data; } +int naettGetTotalBytesRead(naettRes* response, int* totalSize) { + assert(response != NULL); + assert(totalSize != NULL); + + InternalResponse* res = (InternalResponse*)response; + *totalSize = res->contentLength; + return res->totalBytesRead; +} + const char* naettGetHeader(naettRes* response, const char* name) { assert(response != NULL); assert(name != NULL); diff --git a/src/naett_internal.h b/src/naett_internal.h @@ -86,6 +86,8 @@ typedef struct { int complete; KVLink* headers; Buffer body; + int contentLength; // 0 if headers not read, -1 if Content-Length missing. + int totalBytesRead; #if __APPLE__ id session; #endif diff --git a/src/naett_linux.c b/src/naett_linux.c @@ -48,6 +48,7 @@ static void* curlWorker(void* data) { int bytesRead = read(handleReadFD, newHandle.buf, sizeof(newHandle.buf) - newHandlePos); if (bytesRead > 0) { newHandlePos += bytesRead; + res->totalBytesRead += bytesRead; } if (newHandlePos == sizeof(newHandle.buf)) { curl_multi_add_handle(mc, newHandle.handle); diff --git a/src/naett_osx.c b/src/naett_osx.c @@ -106,11 +106,18 @@ void didReceiveData(id self, SEL _sel, id session, id dataTask, id data) { firstHeader = node; } res->headers = firstHeader; + + const char *contentLength = naettGetHeader((naettRes *)res, "Content-Length"); + if (!contentLength || sscanf(contentLength, "%d", &res->contentLength) != 1) { + res->contentLength = -1; + } } const void* bytes = objc_msgSend_t(const void*)(data, sel("bytes")); NSUInteger length = objc_msgSend_t(NSUInteger)(data, sel("length")); + res->request->options.bodyWriter(bytes, length, res->request->options.bodyWriterData); + res->totalBytesRead += (int)length; release(p); } diff --git a/src/naett_win.c b/src/naett_win.c @@ -114,6 +114,11 @@ static void CALLBACK callback(HINTERNET request, unpackHeaders(res, buffer); free(buffer); + const char *contentLength = naettGetHeader((naettRes *)res, "Content-Length"); + if (!contentLength || sscanf(contentLength, "%d", &res->contentLength) != 1) { + res->contentLength = -1; + } + DWORD statusCode = 0; DWORD statusCodeSize = sizeof(statusCode); @@ -154,7 +159,7 @@ static void CALLBACK callback(HINTERNET request, res->code = naettReadError; res->complete = 1; } - + res->totalBytesRead += (int)bytesRead; res->bytesLeft -= bytesRead; if (res->bytesLeft > 0) { size_t bytesToRead = min(res->bytesLeft, sizeof(res->buffer));