Skip to content

Commit

Permalink
added VVCURLDL for doing simple synchronous and asynchronous URL down…
Browse files Browse the repository at this point in the history
…loading and HTTP POSTing because NSURLConnection is slow, big, and apparently not threadsafe
  • Loading branch information
raycutler committed Sep 17, 2009
1 parent cab420e commit 7e1a7bd
Show file tree
Hide file tree
Showing 4 changed files with 208 additions and 0 deletions.
1 change: 1 addition & 0 deletions VVBasics/VVBasics.h
Expand Up @@ -8,6 +8,7 @@
#import "MutLockDict.h"
#import "MutNRLockArray.h"
#import "NamedMutLockArray.h"
#import "VVCURLDL.h"

/*
the following stuff is for doxygen
Expand Down
48 changes: 48 additions & 0 deletions VVBasics/src/VVCURLDL.h
@@ -0,0 +1,48 @@
//
// VVCURLDL.h
// VVOpenSource
//
// Created by bagheera on 9/17/09.
// Copyright 2009 __MyCompanyName__. All rights reserved.
//

#import <Cocoa/Cocoa.h>
#import <curl/curl.h>




@protocol VVCURLDLDelegate
- (void) dlFinished:(id)h;
@end




@interface VVCURLDL : NSObject {
NSString *urlString;
CURL *curlHandle;
NSMutableData *postData;
NSMutableData *responseData;

BOOL returnOnMain;
}

+ (id) createWithAddress:(NSString *)a;
- (id) initWithAddress:(NSString *)a;

- (void) perform;
- (void) performAsync:(BOOL)as withDelegate:(id <VVCURLDLDelegate>)d;
- (void) _performAsyncWithDelegate:(id <VVCURLDLDelegate>)d;
- (void) _performWithDelegate:(id <VVCURLDLDelegate>)d;

- (void) appendDataToPost:(NSData *)d;
- (void) appendStringToPost:(NSString *)s;

- (void) writePtr:(void *)ptr size:(size_t)s;

@property (assign,readonly) BOOL returnOnMain;

@end

size_t vvcurlWriteFunction(void *ptr, size_t size, size_t nmemb, void *stream);
149 changes: 149 additions & 0 deletions VVBasics/src/VVCURLDL.m
@@ -0,0 +1,149 @@
//
// VVCURLDL.m
// VVOpenSource
//
// Created by bagheera on 9/17/09.
// Copyright 2009 __MyCompanyName__. All rights reserved.
//

#import "VVCURLDL.h"




@implementation VVCURLDL


+ (id) createWithAddress:(NSString *)a {
VVCURLDL *returnMe = [[VVCURLDL alloc] initWithAddress:a];
if (returnMe == nil)
return nil;
return [returnMe autorelease];
}
- (id) initWithAddress:(NSString *)a {
if (a==nil)
goto BAIL;
if (self = [super init]) {
urlString = [a retain];
curlHandle = nil;
postData = nil;
responseData = nil;
returnOnMain = NO;
return self;
}
BAIL:
[self release];
return nil;
}
- (void) dealloc {
if (urlString != nil) {
[urlString release];
urlString = nil;
}
if (postData != nil) {
[postData release];
postData = nil;
}
if (responseData != nil) {
[responseData release];
responseData = nil;
}
[super dealloc];
}

- (void) perform {
[self performAsync:NO withDelegate:nil];
}
- (void) performAsync:(BOOL)as withDelegate:(id <VVCURLDLDelegate>)d {
// if i'm performing asynchronously, spawn a thread (make an autorelease pool!) and go
if (as)
[NSThread detachNewThreadSelector:@selector(_performAsyncWithDelegate:) toTarget:self withObject:d];
// else just go
else
[self _performWithDelegate:d];
}
// DO NOT CALL THIS METHOD DIRECTLY
- (void) _performAsyncWithDelegate:(id <VVCURLDLDelegate>)d {
// make a pool
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// perform the download
[self _performWithDelegate:d];
// release the pool
[pool release];
}
// DO NOT CALL THIS METHOD DIRECTLY
- (void) _performWithDelegate:(id <VVCURLDLDelegate>)d {
CURLcode err;

curlHandle = curl_easy_init();
if (curlHandle) {
// set the URL
curl_easy_setopt(curlHandle,CURLOPT_URL,[urlString UTF8String]);
// if there's post data, set that up
if (postData != nil) {
curl_easy_setopt(curlHandle,CURLOPT_POSTFIELDS,[postData bytes]);
}
// set up a write function so libcurl can send me data it receives
curl_easy_setopt(curlHandle,CURLOPT_WRITEFUNCTION,vvcurlWriteFunction);
// i'm going to pass a pointer to myself as the file stream, so i can get back into objective-c
curl_easy_setopt(curlHandle,CURLOPT_WRITEDATA,self);
// perform the transfer
err = curl_easy_perform(curlHandle);
if (err) {
NSLog(@"\terr %ld at curl_easy_perform",err);

}
else {
/*
if (responseData != nil) {
NSString *tmpString = [[[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding] autorelease];
NSLog(@"%@",tmpString);
}
*/
}
// clean up after the transfer
curl_easy_cleanup(curlHandle);
curlHandle = nil;
}
else
NSLog(@"\terror at curl_easy_init() in %s",__func__);

// if there's a delegate, tell the delegate that shit's done
if ((d!=nil)&&([(id)d conformsToProtocol:@protocol(VVCURLDLDelegate)])) {
if (returnOnMain)
[(id)d performSelectorOnMainThread:@selector(dlFinished:) withObject:self waitUntilDone:YES];
[(id)d dlFinished:self];
}
}

- (void) appendDataToPost:(NSData *)d {
if (d == nil)
return;
if (postData == nil)
postData = [[NSMutableData dataWithCapacity:0] retain];
[postData appendData:d];
}
- (void) appendStringToPost:(NSString *)s {
if (s == nil)
return;
[self appendDataToPost:[s dataUsingEncoding:NSUTF8StringEncoding]];
}

- (void) writePtr:(void *)ptr size:(size_t)s {
//NSLog(@"%s",__func__);
if (responseData == nil)
responseData = [[NSMutableData dataWithCapacity:0] retain];
[responseData appendBytes:ptr length:s];
}

@synthesize returnOnMain;


@end


size_t vvcurlWriteFunction(void *ptr, size_t size, size_t nmemb, void *stream) {
if (stream != nil)
[(VVCURLDL *)stream writePtr:ptr size:size*nmemb];
return size*nmemb;
}
10 changes: 10 additions & 0 deletions VVOpenSource.xcodeproj/project.pbxproj
Expand Up @@ -250,6 +250,8 @@
96BF10B0100E95330079A2E6 /* VVOSC.h in Headers */ = {isa = PBXBuildFile; fileRef = 96BF10AD100E95330079A2E6 /* VVOSC.h */; };
96BF10B1100E95330079A2E6 /* VVOSC.h in Headers */ = {isa = PBXBuildFile; fileRef = 96BF10AD100E95330079A2E6 /* VVOSC.h */; };
96C2F2141017815F004E19B0 /* OSCConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 96C2F2131017815F004E19B0 /* OSCConstants.h */; settings = {ATTRIBUTES = (Public, ); }; };
96ED419910628A5500D8373F /* VVCURLDL.h in Headers */ = {isa = PBXBuildFile; fileRef = 96ED419710628A5500D8373F /* VVCURLDL.h */; settings = {ATTRIBUTES = (Public, ); }; };
96ED419A10628A5500D8373F /* VVCURLDL.m in Sources */ = {isa = PBXBuildFile; fileRef = 96ED419810628A5500D8373F /* VVCURLDL.m */; };
BD9F6A0C10191358004D8CD9 /* FreeFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = BD9F6A0A10191358004D8CD9 /* FreeFrame.h */; };
BD9F6A88101921FD004D8CD9 /* FFGL.h in Headers */ = {isa = PBXBuildFile; fileRef = BD9F6A87101921FD004D8CD9 /* FFGL.h */; };
/* End PBXBuildFile section */
Expand Down Expand Up @@ -574,6 +576,8 @@
96BF10C8100E98760079A2E6 /* assembleIPhoneSimSDK.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = assembleIPhoneSimSDK.sh; path = scripts/assembleIPhoneSimSDK.sh; sourceTree = "<group>"; };
96BF10C9100E98930079A2E6 /* assembleMacSDK.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = assembleMacSDK.sh; path = scripts/assembleMacSDK.sh; sourceTree = "<group>"; };
96C2F2131017815F004E19B0 /* OSCConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OSCConstants.h; path = VVOSC/FrameworkSrc/OSCConstants.h; sourceTree = "<group>"; };
96ED419710628A5500D8373F /* VVCURLDL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VVCURLDL.h; path = VVBasics/src/VVCURLDL.h; sourceTree = "<group>"; };
96ED419810628A5500D8373F /* VVCURLDL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VVCURLDL.m; path = VVBasics/src/VVCURLDL.m; sourceTree = "<group>"; };
BD9F6A0A10191358004D8CD9 /* FreeFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FreeFrame.h; path = VVFFGL/FrameworkSrc/FreeFrame.h; sourceTree = "<group>"; };
BD9F6A87101921FD004D8CD9 /* FFGL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FFGL.h; path = VVFFGL/FrameworkSrc/FFGL.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
Expand Down Expand Up @@ -800,6 +804,8 @@
961EA953100E8834007E6C25 /* NamedMutLockArray.m */,
961EA956100E8834007E6C25 /* MutNRLockArray.h */,
961EA955100E8834007E6C25 /* MutNRLockArray.m */,
96ED419710628A5500D8373F /* VVCURLDL.h */,
96ED419810628A5500D8373F /* VVCURLDL.m */,
);
name = "VVBasics framework";
sourceTree = "<group>";
Expand Down Expand Up @@ -927,6 +933,7 @@
961EA964100E8834007E6C25 /* NamedMutLockArray.h in Headers */,
961EA966100E8834007E6C25 /* MutNRLockArray.h in Headers */,
96BF10A9100E95200079A2E6 /* VVBasics.h in Headers */,
96ED419910628A5500D8373F /* VVCURLDL.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -1516,6 +1523,7 @@
961EA961100E8834007E6C25 /* ObjectHolder.m in Sources */,
961EA963100E8834007E6C25 /* NamedMutLockArray.m in Sources */,
961EA965100E8834007E6C25 /* MutNRLockArray.m in Sources */,
96ED419A10628A5500D8373F /* VVCURLDL.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -2000,6 +2008,7 @@
GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
INFOPLIST_FILE = "VVBasics-Info.plist";
INSTALL_PATH = "@executable_path/../Frameworks";
OTHER_LDFLAGS = "-lcurl";
PRODUCT_NAME = VVBasics;
};
name = Debug;
Expand All @@ -2021,6 +2030,7 @@
GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
INFOPLIST_FILE = "VVBasics-Info.plist";
INSTALL_PATH = "@executable_path/../Frameworks";
OTHER_LDFLAGS = "-lcurl";
PRODUCT_NAME = VVBasics;
ZERO_LINK = NO;
};
Expand Down

0 comments on commit 7e1a7bd

Please sign in to comment.