commit 877a4605c1f02117704b56511bc5bc91f05ab807
parent e58caa21f82c916ce34bc2c5153f3c099ee9dee2
Author: Erik Agsjö <erik.agsjo@gmail.com>
Date: Sun, 17 Sep 2023 20:59:47 +0200
Amalgamation
Diffstat:
| M | naett.c | | | 62 | +++++++++++++++++++++++++++++++++++++++++--------------------- |
1 file changed, 41 insertions(+), 21 deletions(-)
diff --git a/naett.c b/naett.c
@@ -613,11 +613,23 @@ static void _showPools(const char* context) {
#define showPools(x)
#endif
-static id pool() {
- return objc_msgSend_id(objc_alloc("NSAutoReleasePool"), sel("init"));
+static id pool(void) {
+ return objc_msgSend_id(objc_alloc("NSAutoreleasePool"), sel("init"));
}
+static id sessionConfiguration = nil;
+
void naettPlatformInit(naettInitData initData) {
+ id NSThread = class("NSThread");
+ SEL isMultiThreaded = sel("isMultiThreaded");
+
+ if (!objc_msgSend_t(bool)(NSThread, isMultiThreaded)) {
+ // Make a dummy call from a new thread to kick Cocoa into multi-threaded mode
+ objc_msgSend_t(void, SEL, id, id)(
+ NSThread, sel("detachNewThreadSelector:toTarget:withObject:"), isMultiThreaded, NSThread, nil);
+ }
+
+ sessionConfiguration = objc_msgSend_id(class("NSURLSessionConfiguration"), sel("ephemeralSessionConfiguration"));
}
id NSString(const char* string) {
@@ -693,7 +705,7 @@ 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;
+ 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")));
@@ -703,7 +715,7 @@ void didReceiveData(id self, SEL _sel, id session, id dataTask, id data) {
}
res->headers = firstHeader;
- const char *contentLength = naettGetHeader((naettRes *)res, "Content-Length");
+ const char* contentLength = naettGetHeader((naettRes*)res, "Content-Length");
if (!contentLength || sscanf(contentLength, "%d", &res->contentLength) != 1) {
res->contentLength = -1;
}
@@ -721,19 +733,20 @@ void didReceiveData(id self, SEL _sel, id session, id dataTask, id data) {
static void didComplete(id self, SEL _sel, id session, id dataTask, id error) {
InternalResponse* res = NULL;
object_getInstanceVariable(self, "response", (void**)&res);
-
- if (error != nil) {
- res->code = naettConnectionError;
+ if (res != NULL) {
+ if (error != nil) {
+ res->code = naettConnectionError;
+ }
+ res->complete = 1;
}
- res->complete = 1;
}
-static id createDelegate() {
- Class TaskDelegateClass = nil;
+static id createDelegate(void) {
+ static Class TaskDelegateClass = nil;
if (!TaskDelegateClass) {
TaskDelegateClass = objc_allocateClassPair((Class)objc_getClass("NSObject"), "naettTaskDelegate", 0);
- class_addProtocol(TaskDelegateClass, objc_getProtocol("NSURLSessionDataDelegate"));
+ class_addProtocol(TaskDelegateClass, (Protocol* _Nonnull)objc_getProtocol("NSURLSessionDataDelegate"));
addMethod(TaskDelegateClass, "URLSession:dataTask:didReceiveData:", didReceiveData, "v@:@@@");
addMethod(TaskDelegateClass, "URLSession:task:didCompleteWithError:", didComplete, "v@:@@@");
@@ -742,7 +755,6 @@ static id createDelegate() {
id delegate = objc_msgSend_id((id)TaskDelegateClass, sel("alloc"));
delegate = objc_msgSend_id(delegate, sel("init"));
- autorelease(delegate);
return delegate;
}
@@ -751,17 +763,20 @@ void naettPlatformMakeRequest(InternalResponse* res) {
InternalRequest* req = res->request;
id p = pool();
- id config = objc_msgSend_id(class("NSURLSessionConfiguration"), sel("ephemeralSessionConfiguration"));
id delegate = createDelegate();
+ // delegate will be retained by session below
+ autorelease(delegate);
+ object_setInstanceVariable(delegate, "response", (void*)res);
- id session = objc_msgSend_t(id, id, id, id)(
- class("NSURLSession"), sel("sessionWithConfiguration:delegate:delegateQueue:"), config, delegate, nil);
+ id session = objc_msgSend_t(id, id, id, id)(class("NSURLSession"),
+ sel("sessionWithConfiguration:delegate:delegateQueue:"),
+ sessionConfiguration,
+ delegate,
+ nil);
- retain(session);
res->session = session;
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(p);
@@ -773,7 +788,8 @@ void naettPlatformFreeRequest(InternalRequest* req) {
}
void naettPlatformCloseResponse(InternalResponse* res) {
- release(res->session);
+ objc_msgSend_void(res->session, sel("invalidateAndCancel"));
+ res->session = nil;
}
#endif // __APPLE__
@@ -1398,7 +1414,9 @@ static int catch (JNIEnv* env) {
static jmethodID getMethod(JNIEnv* env, jobject instance, const char* method, const char* sig) {
jclass clazz = (*env)->GetObjectClass(env, instance);
- return (*env)->GetMethodID(env, clazz, method, sig);
+ jmethodID id = (*env)->GetMethodID(env, clazz, method, sig);
+ (*env)->DeleteLocalRef(env, clazz);
+ return id;
}
static jobject call(JNIEnv* env, jobject instance, const char* method, const char* sig, ...) {
@@ -1433,14 +1451,17 @@ void naettPlatformInit(naettInitData initData) {
int naettPlatformInitRequest(InternalRequest* req) {
JNIEnv* env = getEnv();
+ (*env)->PushLocalFrame(env, 10);
jclass URL = (*env)->FindClass(env, "java/net/URL");
jmethodID newURL = (*env)->GetMethodID(env, URL, "<init>", "(Ljava/lang/String;)V");
jstring urlString = (*env)->NewStringUTF(env, req->url);
jobject url = (*env)->NewObject(env, URL, newURL, urlString);
if (catch (env)) {
+ (*env)->PopLocalFrame(env, NULL);
return 0;
}
req->urlObject = (*env)->NewGlobalRef(env, url);
+ (*env)->PopLocalFrame(env, NULL);
return 1;
}
@@ -1451,7 +1472,7 @@ static void* processRequest(void* data) {
InternalRequest* req = res->request;
JNIEnv* env = getEnv();
- (*env)->PushLocalFrame(env, 10);
+ (*env)->PushLocalFrame(env, 100);
jobject connection = call(env, req->urlObject, "openConnection", "()Ljava/net/URLConnection;");
if (catch (env)) {
@@ -1593,7 +1614,6 @@ finally:
JavaVM* vm = getVM();
(*env)->ExceptionClear(env);
(*vm)->DetachCurrentThread(vm);
- res->workerThread = 0;
return NULL;
}