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 703a562dc80252f42275bd3c2ec934484b980d6b
parent 539143df7a74c3b27ca5a5646dc00876b37f2bfb
Author: Erik Agsjö <erik.agsjo@gmail.com>
Date:   Wed, 10 Nov 2021 22:21:21 +0100

Good enough for now

Diffstat:
Mnaett_internal.h | 3+++
Mnaett_objc.h | 3+++
Mnaett_osx.c | 40++++++++++++++++++++++++++++++++--------
3 files changed, 38 insertions(+), 8 deletions(-)

diff --git a/naett_internal.h b/naett_internal.h @@ -62,6 +62,9 @@ typedef struct { int code; KVLink* headers; Buffer body; +#if __APPLE__ + id session; +#endif } InternalResponse; void naettPlatformInitRequest(InternalRequest* req); diff --git a/naett_objc.h b/naett_objc.h @@ -47,6 +47,9 @@ 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")) +#define retain(OBJ) objc_msgSend_void(OBJ, sel("retain")) +#define release(OBJ) objc_msgSend_void(OBJ, sel("release")) #if __LP64__ || NS_BUILD_32_LIKE_64 #define NSIntegerEncoding "q" diff --git a/naett_osx.c b/naett_osx.c @@ -9,17 +9,24 @@ void naettPlatformInitRequest(InternalRequest* req) { id urlString = objc_msgSend_t(id, const char*)(class("NSString"), sel("stringWithUTF8String:"), req->url); id url = objc_msgSend_t(id, id)(class("NSURL"), sel("URLWithString:"), urlString); + release(urlString); + id request = objc_msgSend_t(id, id)(class("NSMutableURLRequest"), sel("requestWithURL:"), url); + release(url); + objc_msgSend_t(void, double)(request, sel("setTimeoutInterval:"), (double)(req->options.timeoutMS) / 1000.0); id methodString = objc_msgSend_t(id, const char*)(class("NSString"), sel("stringWithUTF8String:"), req->options.method); objc_msgSend_t(void, id)(request, sel("setHTTPMethod:"), methodString); + release(methodString); KVLink* header = req->options.headers; while (header != NULL) { id name = objc_msgSend_t(id, const char*)(class("NSString"), sel("stringWithUTF8String:"), header->key); id value = objc_msgSend_t(id, const char*)(class("NSString"), sel("stringWithUTF8String:"), header->value); objc_msgSend_t(void, id, id)(request, sel("setValue:forHTTPHeaderField:"), name, value); + release(name); + release(value); header = header->next; } @@ -29,6 +36,7 @@ void naettPlatformInitRequest(InternalRequest* req) { id bodyData = objc_msgSend_t(id, void*, NSUInteger, BOOL)( class("NSData"), sel("dataWithBytesNoCopy:length:freeWhenDone:"), body->data, body->size, NO); objc_msgSend_t(void, id)(request, sel("setHTTPBody:"), bodyData); + release(bodyData); } req->urlRequest = request; @@ -62,35 +70,51 @@ void didReceiveData(id self, SEL _sel, id session, id dataTask, id data) { res->request->options.bodyWriter(bytes, length, res->request->options.bodyWriterData); } -void didComplete(id self, SEL _sel, id session, id dataTask, id error) { +static void didComplete(id self, SEL _sel, id session, id dataTask, id error) { InternalResponse* res = NULL; object_getInstanceVariable(self, "response", (void**)&res); res->complete = 1; } -void naettPlatformMakeRequest(InternalRequest* req, InternalResponse* res) { - Class TaskDelegateClass = objc_allocateClassPair((Class)objc_getClass("NSObject"), "TaskDelegate", 0); - addMethod(TaskDelegateClass, "URLSession:dataTask:didReceiveData:", didReceiveData, "v@:@@@"); - addMethod(TaskDelegateClass, "URLSession:task:didCompleteWithError:", didComplete, "v@:@@@"); - addIvar(TaskDelegateClass, "response", sizeof(void*), "^v"); +static id createDelegate() { + Class TaskDelegateClass = nil; - id config = objc_msgSend_id(class("NSURLSessionConfiguration"), sel("ephemeralSessionConfiguration")); + if (!TaskDelegateClass) { + TaskDelegateClass = objc_allocateClassPair((Class)objc_getClass("NSObject"), "naettTaskDelegate", 0); + addMethod(TaskDelegateClass, "URLSession:dataTask:didReceiveData:", didReceiveData, "v@:@@@"); + addMethod(TaskDelegateClass, "URLSession:task:didCompleteWithError:", didComplete, "v@:@@@"); + addIvar(TaskDelegateClass, "response", sizeof(void*), "^v"); + } id delegate = objc_msgSend_id((id)TaskDelegateClass, sel("alloc")); delegate = objc_msgSend_id(delegate, sel("init")); + return delegate; +} + +void naettPlatformMakeRequest(InternalRequest* req, InternalResponse* res) { + id config = objc_msgSend_id(class("NSURLSessionConfiguration"), sel("ephemeralSessionConfiguration")); + id delegate = createDelegate(); + id session = objc_msgSend_t(id, id, id, id)( class("NSURLSession"), sel("sessionWithConfiguration:delegate:delegateQueue:"), config, delegate, nil); - id task = objc_msgSend_t(id, id)(session, sel("dataTaskWithRequest:"), req->urlRequest); + res->session = session; + release(delegate); + + id task = objc_msgSend_t(id, id)(session, sel("dataTaskWithRequest:"), req->urlRequest); object_setInstanceVariable(delegate, "response", (void*)res); objc_msgSend_void(task, sel("resume")); + release(task); } void naettPlatformFreeRequest(InternalRequest* req) { + release(req->urlRequest); + req->urlRequest = nil; } void naettPlatformCloseResponse(InternalResponse* res) { + release(res->session); } #endif // __MACOS__