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 29502cbae8b7a60a1ecb01acec2c13a0512e7e9f
parent 864c851839ab5667ecc39f1633c407e35b649b8a
Author: Henrik RydgÄrd <hrydgard@gmail.com>
Date:   Fri, 21 Jul 2023 17:39:18 +0200

Amalgamation

Diffstat:
Mnaett.c | 55++++++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 46 insertions(+), 9 deletions(-)

diff --git a/naett.c b/naett.c @@ -90,6 +90,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 @@ -430,6 +432,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); @@ -679,18 +690,27 @@ void didReceiveData(id self, SEL _sel, id session, id dataTask, id data) { objc_msgSend_t(NSInteger, id*, id*, NSUInteger)( allHeaders, sel("getObjects:andKeys:count:"), headerValues, headerNames, headerCount); + KVLink *firstHeader = NULL; for (int i = 0; i < headerCount; i++) { naettAlloc(KVLink, node); node->key = strdup(objc_msgSend_t(const char*)(headerNames[i], sel("UTF8String"))); node->value = strdup(objc_msgSend_t(const char*)(headerValues[i], sel("UTF8String"))); - node->next = res->headers; - res->headers = node; + node->next = firstHeader; + 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); } @@ -807,6 +827,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); @@ -1057,6 +1078,7 @@ static LPCWSTR packHeaders(InternalRequest* req) { static void unpackHeaders(InternalResponse* res, LPWSTR packed) { size_t len = 0; + KVLink* firstHeader = NULL; while ((len = wcslen(packed)) != 0) { char* header = winToUTF8(packed); char* split = strchr(header, ':'); @@ -1069,12 +1091,13 @@ static void unpackHeaders(InternalResponse* res, LPWSTR packed) { naettAlloc(KVLink, node); node->key = strdup(header); node->value = strdup(split); - node->next = res->headers; - res->headers = node; + node->next = firstHeader; + firstHeader = node; } free(header); packed += len + 1; } + res->headers = firstHeader; } static void CALLBACK callback(HINTERNET request, @@ -1103,6 +1126,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); @@ -1143,7 +1171,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)); @@ -1492,6 +1520,7 @@ static void* processRequest(void* data) { jarray headers = call(env, headerSet, "toArray", "()[Ljava/lang/Object;"); jsize headerCount = (*env)->GetArrayLength(env, headers); + KVLink *firstHeader = NULL; for (int i = 0; i < headerCount; i++) { jstring name = (*env)->GetObjectArrayElement(env, headers, i); if (name == NULL) { @@ -1506,8 +1535,8 @@ static void* processRequest(void* data) { naettAlloc(KVLink, node); node->key = strdup(nameString); node->value = strdup(valueString); - node->next = res->headers; - res->headers = node; + node->next = firstHeader; + firstHeader = node; (*env)->ReleaseStringUTFChars(env, name, nameString); (*env)->ReleaseStringUTFChars(env, value, valueString); @@ -1516,6 +1545,12 @@ static void* processRequest(void* data) { (*env)->DeleteLocalRef(env, value); (*env)->DeleteLocalRef(env, values); } + 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"); @@ -1540,9 +1575,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");