Improve net request on macos
This commit is contained in:
@@ -1,46 +1,92 @@
|
||||
#include <iron_net.h>
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <objc/runtime.h>
|
||||
|
||||
static NSURLSession *session = nil;
|
||||
volatile uint64_t iron_net_bytes_downloaded = 0;
|
||||
static NSURLSession *download_session = nil;
|
||||
|
||||
@interface IronDownloadDelegate : NSObject <NSURLSessionDownloadDelegate>
|
||||
@end
|
||||
|
||||
@implementation IronDownloadDelegate
|
||||
|
||||
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
|
||||
iron_net_bytes_downloaded += bytesWritten;
|
||||
}
|
||||
|
||||
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
|
||||
NSString *dstPath = objc_getAssociatedObject(downloadTask, @"dst_path");
|
||||
if (dstPath) {
|
||||
NSError *error = nil;
|
||||
NSURL *destURL = [NSURL fileURLWithPath:dstPath];
|
||||
[[NSFileManager defaultManager] moveItemAtURL:location toURL:destURL error:&error];
|
||||
if ([dstPath hasSuffix:@"sd_vulkan"] || [dstPath hasSuffix:@"sd_cpu"]) {
|
||||
NSDictionary *attrs = @{ NSFilePosixPermissions : @0755 };
|
||||
NSError *chmodError = nil;
|
||||
[[NSFileManager defaultManager] setAttributes:attrs ofItemAtPath:dstPath error:&chmodError];
|
||||
}
|
||||
}
|
||||
else {
|
||||
NSData *fileData = [NSData dataWithContentsOfURL:location options:NSDataReadingMappedIfSafe error:nil];
|
||||
NSMutableData *memoryData = objc_getAssociatedObject(downloadTask, @"memoryData");
|
||||
[memoryData appendData:fileData];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
|
||||
NSURLSessionDownloadTask *downloadTask = (NSURLSessionDownloadTask *)task;
|
||||
NSValue *cbVal = objc_getAssociatedObject(task, @"callback");
|
||||
NSValue *dataVal = objc_getAssociatedObject(task, @"callbackdata");
|
||||
NSString *dstPath = objc_getAssociatedObject(task, @"dst_path");
|
||||
NSMutableData *memoryData = objc_getAssociatedObject(task, @"memoryData");
|
||||
iron_https_callback_t callback = cbVal ? [cbVal pointerValue] : NULL;
|
||||
void *callbackdata = dataVal ? [dataVal pointerValue] : NULL;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (dstPath) {
|
||||
callback(NULL, callbackdata);
|
||||
}
|
||||
else {
|
||||
char *buffer = malloc(memoryData.length + 1);
|
||||
memcpy(buffer, memoryData.bytes, memoryData.length);
|
||||
buffer[memoryData.length] = '\0';
|
||||
callback(buffer, callbackdata);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
void iron_net_request(const char *url_base, const char *url_path, const char *data, int port, int method, iron_https_callback_t callback, void *callbackdata, const char *dst_path) {
|
||||
if (session == nil) {
|
||||
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
|
||||
session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
|
||||
if (!download_session) {
|
||||
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
|
||||
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
|
||||
queue.qualityOfService = NSQualityOfServiceUtility;
|
||||
|
||||
static IronDownloadDelegate *delegate = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
delegate = [[IronDownloadDelegate alloc] init];
|
||||
});
|
||||
download_session = [NSURLSession sessionWithConfiguration:config delegate:delegate delegateQueue:queue];
|
||||
}
|
||||
|
||||
NSString *urlstring = @"https://";
|
||||
urlstring = [urlstring stringByAppendingString:[NSString stringWithUTF8String:url_base]];
|
||||
urlstring = [urlstring stringByAppendingString:@":"];
|
||||
urlstring = [urlstring stringByAppendingString:[[NSNumber numberWithInt:port] stringValue]];
|
||||
urlstring = [urlstring stringByAppendingString:@"/"];
|
||||
urlstring = [urlstring stringByAppendingString:[NSString stringWithUTF8String:url_path]];
|
||||
NSURL *aUrl = [NSURL URLWithString:urlstring];
|
||||
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:aUrl];
|
||||
request.HTTPMethod = method == IRON_HTTPS_GET ? @"GET" : @"POST";
|
||||
if (data != 0) {
|
||||
NSString *datastring = [NSString stringWithUTF8String:data];
|
||||
request.HTTPBody = [datastring dataUsingEncoding:NSUTF8StringEncoding];
|
||||
}
|
||||
NSString *urlStr = [NSString stringWithFormat:@"https://%@:%d/%@",
|
||||
[NSString stringWithUTF8String:url_base],
|
||||
port,
|
||||
[NSString stringWithUTF8String:url_path]];
|
||||
NSURL *url = [NSURL URLWithString:urlStr];
|
||||
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
|
||||
request.HTTPMethod = (method == IRON_HTTPS_GET) ? @"GET" : @"POST";
|
||||
|
||||
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
|
||||
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
|
||||
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
char *b = (char *)[data bytes];
|
||||
int len = [data length];
|
||||
char *result = malloc(len + 1);
|
||||
memcpy(result, b, len);
|
||||
result[len] = 0;
|
||||
callback(result, callbackdata);
|
||||
free(result);
|
||||
});
|
||||
}];
|
||||
[dataTask resume];
|
||||
NSURLSessionDownloadTask *task = [download_session downloadTaskWithRequest:request];
|
||||
objc_setAssociatedObject(task, @"callback", [NSValue valueWithPointer:callback], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
objc_setAssociatedObject(task, @"callbackdata", [NSValue valueWithPointer:callbackdata], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
objc_setAssociatedObject(task, @"dst_path", dst_path ? [NSString stringWithUTF8String:dst_path] : nil, OBJC_ASSOCIATION_COPY_NONATOMIC);
|
||||
if (!dst_path) {
|
||||
objc_setAssociatedObject(task, @"memoryData", [NSMutableData data], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
[task resume];
|
||||
}
|
||||
|
||||
void iron_net_update() {
|
||||
}
|
||||
|
||||
volatile uint64_t iron_net_bytes_downloaded = 0;
|
||||
|
||||
Reference in New Issue
Block a user