commit 72eb71fe4a1ba428b8ff5ca03ac31db22b39b86e
parent 28855a6f3dc728770e22f98cb69c6c4e2d642bb9
Author: Erik Agsjö <erik.agsjo@gmail.com>
Date: Sun, 12 Dec 2021 16:19:52 +0100
Amalgam
Diffstat:
| M | naett.c | | | 107 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------- |
1 file changed, 81 insertions(+), 26 deletions(-)
diff --git a/naett.c b/naett.c
@@ -337,6 +337,8 @@ void setupDefaultRW(InternalRequest* req) {
}
naettReq* naettRequest_va(const char* url, int numArgs, ...) {
+ assert(url != NULL);
+
va_list args;
InternalOption* option;
naettAlloc(InternalRequest, req);
@@ -361,6 +363,9 @@ naettReq* naettRequest_va(const char* url, int numArgs, ...) {
}
naettReq* naettRequestWithOptions(const char* url, int numOptions, const naettOption** options) {
+ assert(url != NULL);
+ assert(numOptions == 0 || options != NULL);
+
naettAlloc(InternalRequest, req);
initRequest(req, url);
@@ -382,6 +387,8 @@ naettReq* naettRequestWithOptions(const char* url, int numOptions, const naettOp
naettRes* naettMake(naettReq* request) {
assert(initialized);
+ assert(request != NULL);
+
InternalRequest* req = (InternalRequest*)request;
naettAlloc(InternalResponse, res);
res->request = req;
@@ -395,12 +402,18 @@ naettRes* naettMake(naettReq* request) {
}
const void* naettGetBody(naettRes* response, int* size) {
+ assert(response != NULL);
+ assert(size != NULL);
+
InternalResponse* res = (InternalResponse*)response;
*size = res->body.size;
return res->body.data;
}
const char* naettGetHeader(naettRes* response, const char* name) {
+ assert(response != NULL);
+ assert(name != NULL);
+
InternalResponse* res = (InternalResponse*)response;
KVLink* node = res->headers;
while (node) {
@@ -413,6 +426,9 @@ const char* naettGetHeader(naettRes* response, const char* name) {
}
void naettListHeaders(naettRes* response, naettHeaderLister lister, void* userData) {
+ assert(response != NULL);
+ assert(lister != NULL);
+
InternalResponse* res = (InternalResponse*)response;
KVLink* node = res->headers;
while (node) {
@@ -424,16 +440,19 @@ void naettListHeaders(naettRes* response, naettHeaderLister lister, void* userDa
}
naettReq* naettGetRequest(naettRes* response) {
+ assert(response != NULL);
InternalResponse* res = (InternalResponse*)response;
return (naettReq*) res->request;
}
int naettComplete(const naettRes* response) {
+ assert(response != NULL);
InternalResponse* res = (InternalResponse*)response;
return res->complete;
}
int naettGetStatus(const naettRes* response) {
+ assert(response != NULL);
InternalResponse* res = (InternalResponse*)response;
return res->code;
}
@@ -449,27 +468,22 @@ static void freeKVList(KVLink* node) {
}
void naettFree(naettReq* request) {
+ assert(request != NULL);
+
InternalRequest* req = (InternalRequest*)request;
naettPlatformFreeRequest(req);
- if (req->options.body.data != NULL) {
- free(req->options.body.data);
- }
KVLink* node = req->options.headers;
freeKVList(node);
- if (req->options.body.data != NULL) {
- free(req->options.body.data);
- }
free((void*)req->url);
free(request);
}
void naettClose(naettRes* response) {
+ assert(response != NULL);
+
InternalResponse* res = (InternalResponse*)response;
res->request = NULL;
naettPlatformCloseResponse(res);
- if (res->body.data != NULL) {
- free(res->body.data);
- }
KVLink* node = res->headers;
freeKVList(node);
free(response);
@@ -959,11 +973,12 @@ void naettPlatformCloseResponse(InternalResponse* res) {
#include <stdio.h>
#include <string.h>
#include <winhttp.h>
+#include <assert.h>
void naettPlatformInit(naettInitData initData) {
}
-char* winToUTF8(LPWSTR source) {
+static char* winToUTF8(LPWSTR source) {
int length = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
char* chars = (char*)malloc(length);
int result = WideCharToMultiByte(CP_UTF8, 0, source, -1, chars, length, NULL, NULL);
@@ -974,7 +989,7 @@ char* winToUTF8(LPWSTR source) {
return chars;
}
-LPWSTR winFromUTF8(const char* source) {
+static LPWSTR winFromUTF8(const char* source) {
int length = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0);
LPWSTR chars = (LPWSTR)malloc(length * sizeof(WCHAR));
int result = MultiByteToWideChar(CP_UTF8, 0, source, -1, chars, length);
@@ -992,13 +1007,19 @@ LPWSTR winFromUTF8(const char* source) {
snprintf(*(result), len + 1, fmt, __VA_ARGS__); \
}
-LPCWSTR packHeaders(InternalRequest* req) {
+static LPWSTR wcsndup(LPCWSTR str, size_t len) {
+ LPWSTR result = calloc(1, sizeof(WCHAR) * (len + 1));
+ wcsncpy(result, str, len);
+ return result;
+}
+
+static LPCWSTR packHeaders(InternalRequest* req) {
char* packed = strdup("");
KVLink* node = req->options.headers;
while (node != NULL) {
char* update;
- ASPRINTF(&update, "%s%s=%s%s", packed, node->key, node->value, node->next ? "\r\n" : "");
+ ASPRINTF(&update, "%s%s:%s%s", packed, node->key, node->value, node->next ? "\r\n" : "");
free(packed);
packed = update;
node = node->next;
@@ -1087,7 +1108,7 @@ static void callback(HINTERNET request,
res->code = naettReadError;
res->complete = 1;
}
- }break;
+ } break;
case WINHTTP_CALLBACK_STATUS_READ_COMPLETE: {
size_t bytesRead = statusInfoLength;
@@ -1168,8 +1189,8 @@ int naettPlatformInitRequest(InternalRequest* req) {
return 0;
}
- req->host = wcsncat(wcsdup(L""), components.lpszHostName, components.dwHostNameLength);
- req->resource = wcsncat(wcsdup(L""), components.lpszUrlPath, components.dwUrlPathLength);
+ req->host = wcsndup(components.lpszHostName, components.dwHostNameLength);
+ req->resource = wcsndup(components.lpszUrlPath, components.dwUrlPathLength);
free(url);
req->session = WinHttpOpen(
@@ -1183,7 +1204,7 @@ int naettPlatformInitRequest(InternalRequest* req) {
req->connection = WinHttpConnect(req->session, req->host, components.nPort, 0);
if (!req->connection) {
- WinHttpCloseHandle(req->session);
+ naettPlatformFreeRequest(req);
return 0;
}
@@ -1197,31 +1218,65 @@ int naettPlatformInitRequest(InternalRequest* req) {
components.nScheme == INTERNET_SCHEME_HTTPS ? WINHTTP_FLAG_SECURE : 0);
free(verb);
if (!req->request) {
- WinHttpCloseHandle(req->session);
- WinHttpCloseHandle(req->connection);
+ naettPlatformFreeRequest(req);
return 0;
}
LPCWSTR headers = packHeaders(req);
- WinHttpAddRequestHeaders(req->request, headers, 0, WINHTTP_ADDREQ_FLAG_ADD);
+ if (headers[0] != 0) {
+ if (!WinHttpAddRequestHeaders(
+ req->request, headers, -1, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE)) {
+ naettPlatformFreeRequest(req);
+ free((LPWSTR)headers);
+ return 0;
+ }
+ }
free((LPWSTR)headers);
return 1;
}
void naettPlatformMakeRequest(InternalResponse* res) {
- if (!WinHttpSendRequest(res->request->request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, NULL, 0, 0, (DWORD_PTR)res)) {
+ InternalRequest* req = res->request;
+
+ LPCWSTR extraHeaders = WINHTTP_NO_ADDITIONAL_HEADERS;
+ WCHAR contentLengthHeader[64];
+
+ int contentLength = req->options.bodyReader(NULL, 0, req->options.bodyReaderData);
+ if (contentLength > 0) {
+ wsprintfW(contentLengthHeader, L"Content-Length: %d", contentLength);
+ extraHeaders = contentLengthHeader;
+ }
+
+ if (!WinHttpSendRequest(req->request, extraHeaders, -1, NULL, 0, 0, (DWORD_PTR)res)) {
res->code = naettConnectionError;
res->complete = 1;
}
}
void naettPlatformFreeRequest(InternalRequest* req) {
- WinHttpCloseHandle(req->session);
- WinHttpCloseHandle(req->connection);
- WinHttpCloseHandle(req->request);
- free(req->host);
- free(req->resource);
+ assert(req != NULL);
+
+ if (req->request != NULL) {
+ WinHttpCloseHandle(req->request);
+ req->request = NULL;
+ }
+ if (req->connection != NULL) {
+ WinHttpCloseHandle(req->connection);
+ req->connection = NULL;
+ }
+ if (req->session != NULL) {
+ WinHttpCloseHandle(req->session);
+ req->session = NULL;
+ }
+ if (req->host != NULL) {
+ free(req->host);
+ req->host = NULL;
+ }
+ if (req->resource != NULL) {
+ free(req->resource);
+ req->resource = NULL;
+ }
}
void naettPlatformCloseResponse(InternalResponse* res) {