commit c9523b511fb3a3e1edc8e08a8f3577fb64dd1000
parent 5853eb1f7f6458a277f1264e2305b33cf2712aa9
Author: Erik Agsjö <erik.agsjo@gmail.com>
Date: Mon, 6 Dec 2021 00:04:13 +0100
First win version
Diffstat:
6 files changed, 554 insertions(+), 12 deletions(-)
diff --git a/example/Makefile b/example/Makefile
@@ -1,12 +1,13 @@
-CFLAGS = -I.. -g -Wall -pedantic -Wno-gnu-zero-variadic-macro-arguments
+CFLAGS = -I.. -g -Wall -pedantic
#CFLAGS = -O2
ifeq ($(OS),Windows_NT)
-
+ LDFLAGS = -lwinhttp
else
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
LDFLAGS = -framework Cocoa
+ CFLAGS += -Wno-gnu-zero-variadic-macro-arguments
else ifeq ($(UNAME_S),Linux)
LDFLAGS = -lcurl -lpthread
endif
diff --git a/naett.c b/naett.c
@@ -8,6 +8,7 @@
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
+#include <winhttp.h>
#define __WINDOWS__ 1
#endif
@@ -66,6 +67,13 @@ typedef struct {
#if __ANDROID__
jobject urlObject;
#endif
+#if __WINDOWS__
+ HINTERNET session;
+ HINTERNET connection;
+ HINTERNET request;
+ LPWSTR host;
+ LPWSTR resource;
+#endif
} InternalRequest;
typedef struct {
@@ -84,6 +92,10 @@ typedef struct {
#if __LINUX__
struct curl_slist* headerList;
#endif
+#if __WINDOWS__
+ char buffer[10240];
+ size_t bytesLeft;
+#endif
} InternalResponse;
void naettPlatformInit(naettInitData initData);
@@ -503,14 +515,17 @@ void naettClose(naettRes* response) {
#define sel(NAME) sel_registerName(NAME)
#define class(NAME) ((id)objc_getClass(NAME))
-#define makeClass(NAME, SUPER) objc_allocateClassPair((Class)objc_getClass(SUPER), NAME, 0)
+#define makeClass(NAME, SUPER) \
+ objc_allocateClassPair((Class)objc_getClass(SUPER), NAME, 0)
// Check here to get the signature right:
// https://nshipster.com/type-encodings/
// https://ko9.org/posts/encode-types/
-#define addMethod(CLASS, NAME, IMPL, SIGNATURE) if (!class_addMethod(CLASS, sel(NAME), (IMP) (IMPL), (SIGNATURE))) assert(false)
+#define addMethod(CLASS, NAME, IMPL, SIGNATURE) \
+ if (!class_addMethod(CLASS, sel(NAME), (IMP) (IMPL), (SIGNATURE))) assert(false)
-#define addIvar(CLASS, NAME, SIZE, SIGNATURE) if (!class_addIvar(CLASS, NAME, SIZE, rint(log2(SIZE)), SIGNATURE)) assert(false)
+#define addIvar(CLASS, NAME, SIZE, SIGNATURE) \
+ if (!class_addIvar(CLASS, NAME, SIZE, rint(log2(SIZE)), SIGNATURE)) assert(false)
#define objc_alloc(CLASS) objc_msgSend_id(class(CLASS), sel("alloc"))
#define autorelease(OBJ) objc_msgSend_void(OBJ, sel("autorelease"))
@@ -535,7 +550,7 @@ void naettClose(naettRes* response) {
#ifdef DEBUG
static void _showPools(const char* context) {
- fprintf(stderr, "NSAutoreleasePool@%s:n", context);
+ fprintf(stderr, "NSAutoreleasePool@%s:\n", context);
objc_msgSend_void(class("NSAutoreleasePool"), sel("showPools"));
}
#define showPools(x) _showPools((x))
@@ -706,7 +721,7 @@ static int handleReadFD = 0;
static int handleWriteFD = 0;
static void panic(const char* message) {
- fprintf(stderr, "%sn", message);
+ fprintf(stderr, "%s\n", message);
exit(1);
}
@@ -920,18 +935,276 @@ void naettPlatformCloseResponse(InternalResponse* res) {
#ifdef __WINDOWS__
#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
+#include <winhttp.h>
+
+void naettPlatformInit(naettInitData initData) {
+}
+
+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);
+ if (!result) {
+ free(chars);
+ return NULL;
+ }
+ return chars;
+}
+
+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);
+ if (!result) {
+ free(chars);
+ return NULL;
+ }
+ return chars;
+}
+
+#define ASPRINTF(result, fmt, ...) \
+ { \
+ size_t len = snprintf(NULL, 0, fmt, __VA_ARGS__); \
+ *(result) = (char*)malloc(len + 1); \
+ snprintf(*(result), len + 1, fmt, __VA_ARGS__); \
+ }
+
+LPCWSTR packHeaders(InternalRequest* req) {
+ char* packed = strdup("");
-void naettPlatformInit(naettInitData initData) {
+ 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" : "");
+ free(packed);
+ packed = update;
+ node = node->next;
+ }
+
+ LPCWSTR winHeaders = winFromUTF8(packed);
+ free(packed);
+ return winHeaders;
+}
+
+static void unpackHeaders(InternalResponse* res, LPWSTR packed) {
+ int len = 0;
+ while ((len = wcslen(packed)) != 0) {
+ char* header = winToUTF8(packed);
+ char* split = strchr(header, ':');
+ if (split) {
+ *split = 0;
+ split++;
+ while (*split == ' ') {
+ split++;
+ }
+ naettAlloc(KVLink, node);
+ node->key = strdup(header);
+ node->value = strdup(split);
+ node->next = res->headers;
+ res->headers = node;
+ printf("Unpacked header: %s=%s\n", node->key, node->value);
+ }
+ free(header);
+ packed += len + 1;
+ }
+}
+
+static void callback(HINTERNET request,
+ DWORD_PTR context,
+ DWORD status,
+ LPVOID statusInformation,
+ DWORD statusInfoLength) {
+ InternalResponse* res = (InternalResponse*)context;
+
+ switch (status) {
+ case WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE: {
+ DWORD bufSize = 0;
+ WinHttpQueryHeaders(request,
+ WINHTTP_QUERY_RAW_HEADERS,
+ WINHTTP_HEADER_NAME_BY_INDEX,
+ NULL,
+ &bufSize,
+ WINHTTP_NO_HEADER_INDEX);
+ LPWSTR buffer = (LPWSTR)malloc(bufSize);
+ WinHttpQueryHeaders(request,
+ WINHTTP_QUERY_RAW_HEADERS,
+ WINHTTP_HEADER_NAME_BY_INDEX,
+ buffer,
+ &bufSize,
+ WINHTTP_NO_HEADER_INDEX);
+ unpackHeaders(res, buffer);
+ free(buffer);
+
+ DWORD statusCode = 0;
+ DWORD statusCodeSize = sizeof(statusCode);
+
+ WinHttpQueryHeaders(request,
+ WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
+ WINHTTP_HEADER_NAME_BY_INDEX,
+ &statusCode,
+ &statusCodeSize,
+ WINHTTP_NO_HEADER_INDEX);
+ res->code = statusCode;
+
+ if (!WinHttpQueryDataAvailable(request, NULL)) {
+ res->code = naettProtocolError;
+ res->complete = 1;
+ }
+ } break;
+
+ case WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE: {
+ DWORD* available = (DWORD*)statusInformation;
+ res->bytesLeft = *available;
+ if (res->bytesLeft == 0) {
+ res->complete = 1;
+ break;
+ }
+
+ size_t bytesToRead = min(res->bytesLeft, sizeof(res->buffer));
+ if (!WinHttpReadData(request, res->buffer, bytesToRead, NULL)) {
+ res->code = naettReadError;
+ res->complete = 1;
+ }
+ }break;
+
+ case WINHTTP_CALLBACK_STATUS_READ_COMPLETE: {
+ size_t bytesRead = statusInfoLength;
+
+ InternalRequest* req = res->request;
+ if (req->options.bodyWriter(res->buffer, bytesRead, req->options.bodyWriterData) != bytesRead) {
+ res->code = naettReadError;
+ res->complete = 1;
+ }
+
+ res->bytesLeft -= bytesRead;
+ if (res->bytesLeft > 0) {
+ size_t bytesToRead = min(res->bytesLeft, sizeof(res->buffer));
+ if (!WinHttpReadData(request, res->buffer, bytesToRead, NULL)) {
+ res->code = naettReadError;
+ res->complete = 1;
+ }
+ } else {
+ if (!WinHttpQueryDataAvailable(request, NULL)) {
+ res->code = naettProtocolError;
+ res->complete = 1;
+ }
+ }
+ } break;
+
+ case WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE:
+ case WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE: {
+ int bytesRead = res->request->options.bodyReader(
+ res->buffer, sizeof(res->buffer), res->request->options.bodyReaderData);
+ if (bytesRead) {
+ WinHttpWriteData(request, res->buffer, bytesRead, NULL);
+ } else {
+ if (!WinHttpReceiveResponse(request, NULL)) {
+ res->code = naettReadError;
+ res->complete = 1;
+ }
+ }
+ } break;
+
+ //
+ case WINHTTP_CALLBACK_STATUS_REQUEST_ERROR: {
+ WINHTTP_ASYNC_RESULT* result = (WINHTTP_ASYNC_RESULT*)statusInformation;
+ switch (result->dwResult) {
+ case API_RECEIVE_RESPONSE:
+ case API_QUERY_DATA_AVAILABLE:
+ case API_READ_DATA:
+ res->code = naettReadError;
+ break;
+ case API_WRITE_DATA:
+ res->code = naettWriteError;
+ break;
+ case API_SEND_REQUEST:
+ res->code = naettConnectionError;
+ break;
+ default:
+ res->code = naettGenericError;
+ }
+
+ res->complete = 1;
+ } break;
+ }
}
int naettPlatformInitRequest(InternalRequest* req) {
+ LPWSTR url = winFromUTF8(req->url);
+ printf("Connecting to %S\n", url);
+
+ URL_COMPONENTS components;
+ ZeroMemory(&components, sizeof(components));
+ components.dwStructSize = sizeof(components);
+ components.dwSchemeLength = (DWORD)-1;
+ components.dwHostNameLength = (DWORD)-1;
+ components.dwUrlPathLength = (DWORD)-1;
+ components.dwExtraInfoLength = (DWORD)-1;
+ BOOL cracked = WinHttpCrackUrl(url, 0, 0, &components);
+
+ if (!cracked) {
+ free(url);
+ return 0;
+ }
+
+ req->host = wcsncat(wcsdup(L""), components.lpszHostName, components.dwHostNameLength);
+ req->resource = wcsncat(wcsdup(L""), components.lpszUrlPath, components.dwUrlPathLength);
+ free(url);
+
+ req->session = WinHttpOpen(
+ L"Naett/1.0", WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, WINHTTP_FLAG_ASYNC);
+
+ if (!req->session) {
+ return 0;
+ }
+
+ WinHttpSetStatusCallback(req->session, callback, WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS, 0);
+
+ req->connection = WinHttpConnect(req->session, req->host, components.nPort, 0);
+ if (!req->connection) {
+ WinHttpCloseHandle(req->session);
+ return 0;
+ }
+
+ LPWSTR verb = winFromUTF8(req->options.method);
+ req->request = WinHttpOpenRequest(req->connection,
+ verb,
+ req->resource,
+ NULL,
+ WINHTTP_NO_REFERER,
+ WINHTTP_DEFAULT_ACCEPT_TYPES,
+ components.nScheme == INTERNET_SCHEME_HTTPS ? WINHTTP_FLAG_SECURE : 0);
+ free(verb);
+ if (!req->request) {
+ WinHttpCloseHandle(req->session);
+ WinHttpCloseHandle(req->connection);
+ return 0;
+ }
+
+ LPCWSTR headers = packHeaders(req);
+ WinHttpAddRequestHeaders(req->request, headers, 0, WINHTTP_ADDREQ_FLAG_ADD);
+ printf("Request headers: %S\n", headers);
+ free((LPWSTR)headers);
+
+ return 1;
}
-void naettPlatformMakeRequest(InternalRequest* req, InternalResponse* res) {
+void naettPlatformMakeRequest(InternalResponse* res) {
+ if (!WinHttpSendRequest(res->request->request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, NULL, 0, 0, (DWORD_PTR)res)) {
+ printf("Failed to send request\n");
+ 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);
}
void naettPlatformCloseResponse(InternalResponse* res) {
diff --git a/naett.h b/naett.h
@@ -79,6 +79,8 @@ enum naettStatus {
naettConnectionError = -1,
naettProtocolError = -2,
naettReadError = -3,
+ naettWriteError = -4,
+ naettGenericError = -5,
naettProcessing = 0,
};
diff --git a/src/bundle.sh b/src/bundle.sh
@@ -18,7 +18,7 @@ bundle() {
echo "// Inlined $file: //" >> "$target"
IFS=""
- while read line; do
+ while read -r line; do
if [[ $line =~ ^\#include\ \"(.+)\" && -f ${BASH_REMATCH[1]} ]]; then
include=${BASH_REMATCH[1]}
if bundle $include; then
diff --git a/src/naett_internal.h b/src/naett_internal.h
@@ -4,6 +4,7 @@
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
+#include <winhttp.h>
#define __WINDOWS__ 1
#endif
@@ -62,6 +63,13 @@ typedef struct {
#if __ANDROID__
jobject urlObject;
#endif
+#if __WINDOWS__
+ HINTERNET session;
+ HINTERNET connection;
+ HINTERNET request;
+ LPWSTR host;
+ LPWSTR resource;
+#endif
} InternalRequest;
typedef struct {
@@ -80,6 +88,10 @@ typedef struct {
#if __LINUX__
struct curl_slist* headerList;
#endif
+#if __WINDOWS__
+ char buffer[10240];
+ size_t bytesLeft;
+#endif
} InternalResponse;
void naettPlatformInit(naettInitData initData);
diff --git a/src/naett_win.c b/src/naett_win.c
@@ -3,18 +3,272 @@
#ifdef __WINDOWS__
#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
+#include <winhttp.h>
-void naettPlatformInit(naettInitData initData) {
+void naettPlatformInit(naettInitData initData) {
+}
+
+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);
+ if (!result) {
+ free(chars);
+ return NULL;
+ }
+ return chars;
+}
+
+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);
+ if (!result) {
+ free(chars);
+ return NULL;
+ }
+ return chars;
+}
+
+#define ASPRINTF(result, fmt, ...) \
+ { \
+ size_t len = snprintf(NULL, 0, fmt, __VA_ARGS__); \
+ *(result) = (char*)malloc(len + 1); \
+ snprintf(*(result), len + 1, fmt, __VA_ARGS__); \
+ }
+
+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" : "");
+ free(packed);
+ packed = update;
+ node = node->next;
+ }
+
+ LPCWSTR winHeaders = winFromUTF8(packed);
+ free(packed);
+ return winHeaders;
+}
+
+static void unpackHeaders(InternalResponse* res, LPWSTR packed) {
+ int len = 0;
+ while ((len = wcslen(packed)) != 0) {
+ char* header = winToUTF8(packed);
+ char* split = strchr(header, ':');
+ if (split) {
+ *split = 0;
+ split++;
+ while (*split == ' ') {
+ split++;
+ }
+ naettAlloc(KVLink, node);
+ node->key = strdup(header);
+ node->value = strdup(split);
+ node->next = res->headers;
+ res->headers = node;
+ }
+ free(header);
+ packed += len + 1;
+ }
+}
+
+static void callback(HINTERNET request,
+ DWORD_PTR context,
+ DWORD status,
+ LPVOID statusInformation,
+ DWORD statusInfoLength) {
+ InternalResponse* res = (InternalResponse*)context;
+
+ switch (status) {
+ case WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE: {
+ DWORD bufSize = 0;
+ WinHttpQueryHeaders(request,
+ WINHTTP_QUERY_RAW_HEADERS,
+ WINHTTP_HEADER_NAME_BY_INDEX,
+ NULL,
+ &bufSize,
+ WINHTTP_NO_HEADER_INDEX);
+ LPWSTR buffer = (LPWSTR)malloc(bufSize);
+ WinHttpQueryHeaders(request,
+ WINHTTP_QUERY_RAW_HEADERS,
+ WINHTTP_HEADER_NAME_BY_INDEX,
+ buffer,
+ &bufSize,
+ WINHTTP_NO_HEADER_INDEX);
+ unpackHeaders(res, buffer);
+ free(buffer);
+
+ DWORD statusCode = 0;
+ DWORD statusCodeSize = sizeof(statusCode);
+
+ WinHttpQueryHeaders(request,
+ WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
+ WINHTTP_HEADER_NAME_BY_INDEX,
+ &statusCode,
+ &statusCodeSize,
+ WINHTTP_NO_HEADER_INDEX);
+ res->code = statusCode;
+
+ if (!WinHttpQueryDataAvailable(request, NULL)) {
+ res->code = naettProtocolError;
+ res->complete = 1;
+ }
+ } break;
+
+ case WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE: {
+ DWORD* available = (DWORD*)statusInformation;
+ res->bytesLeft = *available;
+ if (res->bytesLeft == 0) {
+ res->complete = 1;
+ break;
+ }
+
+ size_t bytesToRead = min(res->bytesLeft, sizeof(res->buffer));
+ if (!WinHttpReadData(request, res->buffer, bytesToRead, NULL)) {
+ res->code = naettReadError;
+ res->complete = 1;
+ }
+ }break;
+
+ case WINHTTP_CALLBACK_STATUS_READ_COMPLETE: {
+ size_t bytesRead = statusInfoLength;
+
+ InternalRequest* req = res->request;
+ if (req->options.bodyWriter(res->buffer, bytesRead, req->options.bodyWriterData) != bytesRead) {
+ res->code = naettReadError;
+ res->complete = 1;
+ }
+
+ res->bytesLeft -= bytesRead;
+ if (res->bytesLeft > 0) {
+ size_t bytesToRead = min(res->bytesLeft, sizeof(res->buffer));
+ if (!WinHttpReadData(request, res->buffer, bytesToRead, NULL)) {
+ res->code = naettReadError;
+ res->complete = 1;
+ }
+ } else {
+ if (!WinHttpQueryDataAvailable(request, NULL)) {
+ res->code = naettProtocolError;
+ res->complete = 1;
+ }
+ }
+ } break;
+
+ case WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE:
+ case WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE: {
+ int bytesRead = res->request->options.bodyReader(
+ res->buffer, sizeof(res->buffer), res->request->options.bodyReaderData);
+ if (bytesRead) {
+ WinHttpWriteData(request, res->buffer, bytesRead, NULL);
+ } else {
+ if (!WinHttpReceiveResponse(request, NULL)) {
+ res->code = naettReadError;
+ res->complete = 1;
+ }
+ }
+ } break;
+
+ //
+ case WINHTTP_CALLBACK_STATUS_REQUEST_ERROR: {
+ WINHTTP_ASYNC_RESULT* result = (WINHTTP_ASYNC_RESULT*)statusInformation;
+ switch (result->dwResult) {
+ case API_RECEIVE_RESPONSE:
+ case API_QUERY_DATA_AVAILABLE:
+ case API_READ_DATA:
+ res->code = naettReadError;
+ break;
+ case API_WRITE_DATA:
+ res->code = naettWriteError;
+ break;
+ case API_SEND_REQUEST:
+ res->code = naettConnectionError;
+ break;
+ default:
+ res->code = naettGenericError;
+ }
+
+ res->complete = 1;
+ } break;
+ }
}
int naettPlatformInitRequest(InternalRequest* req) {
+ LPWSTR url = winFromUTF8(req->url);
+
+ URL_COMPONENTS components;
+ ZeroMemory(&components, sizeof(components));
+ components.dwStructSize = sizeof(components);
+ components.dwSchemeLength = (DWORD)-1;
+ components.dwHostNameLength = (DWORD)-1;
+ components.dwUrlPathLength = (DWORD)-1;
+ components.dwExtraInfoLength = (DWORD)-1;
+ BOOL cracked = WinHttpCrackUrl(url, 0, 0, &components);
+
+ if (!cracked) {
+ free(url);
+ return 0;
+ }
+
+ req->host = wcsncat(wcsdup(L""), components.lpszHostName, components.dwHostNameLength);
+ req->resource = wcsncat(wcsdup(L""), components.lpszUrlPath, components.dwUrlPathLength);
+ free(url);
+
+ req->session = WinHttpOpen(
+ L"Naett/1.0", WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, WINHTTP_FLAG_ASYNC);
+
+ if (!req->session) {
+ return 0;
+ }
+
+ WinHttpSetStatusCallback(req->session, callback, WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS, 0);
+
+ req->connection = WinHttpConnect(req->session, req->host, components.nPort, 0);
+ if (!req->connection) {
+ WinHttpCloseHandle(req->session);
+ return 0;
+ }
+
+ LPWSTR verb = winFromUTF8(req->options.method);
+ req->request = WinHttpOpenRequest(req->connection,
+ verb,
+ req->resource,
+ NULL,
+ WINHTTP_NO_REFERER,
+ WINHTTP_DEFAULT_ACCEPT_TYPES,
+ components.nScheme == INTERNET_SCHEME_HTTPS ? WINHTTP_FLAG_SECURE : 0);
+ free(verb);
+ if (!req->request) {
+ WinHttpCloseHandle(req->session);
+ WinHttpCloseHandle(req->connection);
+ return 0;
+ }
+
+ LPCWSTR headers = packHeaders(req);
+ WinHttpAddRequestHeaders(req->request, headers, 0, WINHTTP_ADDREQ_FLAG_ADD);
+ free((LPWSTR)headers);
+
+ return 1;
}
-void naettPlatformMakeRequest(InternalRequest* req, InternalResponse* res) {
+void naettPlatformMakeRequest(InternalResponse* res) {
+ if (!WinHttpSendRequest(res->request->request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, 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);
}
void naettPlatformCloseResponse(InternalResponse* res) {