Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Classes/ASIAuthenticationDialog.m
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ - (void)viewDidDisappear:(BOOL)animated
sharedDialog = nil;
[self performSelector:@selector(presentNextDialog) withObject:nil afterDelay:0];
[self release];
[super viewDidDisappear:animated];
}

- (void)dismiss
Expand Down
6 changes: 3 additions & 3 deletions Classes/ASIHTTPRequest.m
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#import "ASIDataCompressor.h"

// Automatically set on build
NSString *ASIHTTPRequestVersion = @"v1.8.1-61 2011-09-19";
NSString *ASIHTTPRequestVersion = @"v1.8.2-14 2014-09-19";

static NSString *defaultUserAgent = nil;

Expand Down Expand Up @@ -4434,7 +4434,7 @@ + (NSString *)defaultUserAgentString
if (err != noErr) return nil;
err = Gestalt(gestaltSystemVersionBugFix, &versionBugFix);
if (err != noErr) return nil;
OSVersion = [NSString stringWithFormat:@"%u.%u.%u", versionMajor, versionMinor, versionBugFix];
OSVersion = [NSString stringWithFormat:@"%u.%u.%u", (int)versionMajor, (int)versionMinor, (int)versionBugFix];
#endif

// Takes the form "My Application 1.0 (Macintosh; Mac OS X 10.5.7; en_GB)"
Expand Down Expand Up @@ -4622,7 +4622,7 @@ + (unsigned long)maxUploadReadLength

// We'll split our bandwidth allowance into 4 (which is the default for an ASINetworkQueue's max concurrent operations count) to give all running requests a fighting chance of reading data this cycle
long long toRead = maxBandwidthPerSecond/4;
if (maxBandwidthPerSecond > 0 && (bandwidthUsedInLastSecond + toRead > maxBandwidthPerSecond)) {
if (maxBandwidthPerSecond > 0 && (((long long)bandwidthUsedInLastSecond + toRead) > (long long)maxBandwidthPerSecond)) {
toRead = (long long)maxBandwidthPerSecond-(long long)bandwidthUsedInLastSecond;
if (toRead < 0) {
toRead = 0;
Expand Down
14 changes: 10 additions & 4 deletions Classes/ASIInputStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,19 @@
// Subclassing NSInputStream seems to be tricky, and may involve overriding undocumented methods, so we'll cheat instead.
// It is used by ASIHTTPRequest whenever we have a request body, and handles measuring and throttling the bandwidth used for uploading

@interface ASIInputStream : NSObject {
NSInputStream *stream;
ASIHTTPRequest *request;
@interface ASIInputStream : NSObject<NSStreamDelegate>{
NSInputStream *stream;
id<NSStreamDelegate> delegate;

CFReadStreamClientCallBack copiedCallback;
CFStreamClientContext copiedContext;
CFOptionFlags requestedEvents;
ASIHTTPRequest *request;
}

+ (id)inputStreamWithFileAtPath:(NSString *)path request:(ASIHTTPRequest *)request;
+ (id)inputStreamWithData:(NSData *)data request:(ASIHTTPRequest *)request;
- (id)initWithInputStream:(NSInputStream *)stream;

@property (retain, nonatomic) NSInputStream *stream;
@property (assign, nonatomic) ASIHTTPRequest *request;
@end
233 changes: 185 additions & 48 deletions Classes/ASIInputStream.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#import "ASIInputStream.h"
#import "ASIHTTPRequest.h"
#import <objc/runtime.h>

// Used to ensure only one request can read data at once
static NSLock *readLock = nil;
Expand All @@ -16,60 +17,49 @@ @implementation ASIInputStream

+ (void)initialize
{
if (self == [ASIInputStream class]) {
readLock = [[NSLock alloc] init];
}
if (self == [ASIInputStream class]) {
readLock = [[NSLock alloc] init];
}
}

+ (id)inputStreamWithFileAtPath:(NSString *)path request:(ASIHTTPRequest *)theRequest
{
ASIInputStream *theStream = [[[self alloc] init] autorelease];
[theStream setRequest:theRequest];
[theStream setStream:[NSInputStream inputStreamWithFileAtPath:path]];
return theStream;
ASIInputStream *theStream = [[[ASIInputStream alloc] initWithInputStream:[NSInputStream inputStreamWithFileAtPath:path]] autorelease];
[theStream setRequest:theRequest];
return theStream;
}

+ (id)inputStreamWithData:(NSData *)data request:(ASIHTTPRequest *)theRequest
{
ASIInputStream *theStream = [[[self alloc] init] autorelease];
[theStream setRequest:theRequest];
[theStream setStream:[NSInputStream inputStreamWithData:data]];
return theStream;
ASIInputStream *theStream = [[[ASIInputStream alloc] initWithInputStream:[NSInputStream inputStreamWithData:data]] autorelease];
[theStream setRequest:theRequest];
return theStream;
}

- (void)dealloc
#pragma mark - Object lifecycle

- (id)initWithInputStream:(NSInputStream *)aStream
{
[stream release];
[super dealloc];
self = [super init];
if (self) {
// Initialization code here.
stream = [aStream retain];
[stream setDelegate:self];

[self setDelegate:self];
}

return self;
}

// Called when CFNetwork wants to read more of our request body
// When throttling is on, we ask ASIHTTPRequest for the maximum amount of data we can read
- (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)len
- (void)dealloc
{
[readLock lock];
unsigned long toRead = len;
if ([ASIHTTPRequest isBandwidthThrottled]) {
toRead = [ASIHTTPRequest maxUploadReadLength];
if (toRead > len) {
toRead = len;
} else if (toRead == 0) {
toRead = 1;
}
[request performThrottling];
}
[readLock unlock];
NSInteger rv = [stream read:buffer maxLength:toRead];
if (rv > 0)
[ASIHTTPRequest incrementBandwidthUsedInLastSecond:(NSUInteger)rv];
return rv;
}

/*
* Implement NSInputStream mandatory methods to make sure they are implemented
* (necessary for MacRuby for example) and avoid the overhead of method
* forwarding for these common methods.
*/
[stream release];
[super dealloc];
}

#pragma mark - NSStream subclass methods

- (void)open
{
[stream open];
Expand All @@ -80,14 +70,19 @@ - (void)close
[stream close];
}

- (id)delegate
- (id <NSStreamDelegate> )delegate
{
return [stream delegate];
return delegate;
}

- (void)setDelegate:(id)delegate
- (void)setDelegate:(id<NSStreamDelegate>)aDelegate
{
[stream setDelegate:delegate];
if (aDelegate == nil) {
delegate = self;
}
else {
delegate = aDelegate;
}
}

- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode
Expand Down Expand Up @@ -120,19 +115,161 @@ - (NSError *)streamError
return [stream streamError];
}

#pragma mark - NSInputStream subclass methods

// Called when CFNetwork wants to read more of our request body
// When throttling is on, we ask ASIHTTPRequest for the maximum amount of data we can read
- (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)len
{
[readLock lock];
unsigned long toRead = len;
if ([ASIHTTPRequest isBandwidthThrottled]) {
toRead = [ASIHTTPRequest maxUploadReadLength];
if (toRead > len) {
toRead = len;
} else if (toRead == 0) {
toRead = 1;
}
[request performThrottling];
}
[readLock unlock];
NSInteger rv = [stream read:buffer maxLength:toRead];
if (rv > 0)
[ASIHTTPRequest incrementBandwidthUsedInLastSecond:(unsigned long)rv];
return rv;
}


- (BOOL)getBuffer:(uint8_t **)buffer length:(NSUInteger *)len
{
// We cannot implement our character-counting in O(1) time,
// so we return NO as indicated in the NSInputStream
// documentation.
return NO;
}

- (BOOL)hasBytesAvailable
{
return [stream hasBytesAvailable];
}

#pragma mark - Undocumented CFReadStream bridged methods

+ (BOOL)resolveInstanceMethod:(SEL) selector
{
NSString *name = NSStringFromSelector(selector);

if ([name hasPrefix:@"_"]){
name = [name substringFromIndex:1];
SEL aSelector = NSSelectorFromString(name);
Method method = class_getInstanceMethod(self, aSelector);

if (method)
{
class_addMethod(self,
selector,
method_getImplementation(method),
method_getTypeEncoding(method));
return YES;
}
}
return [super resolveInstanceMethod:selector];
}

- (void)scheduleInCFRunLoop:(CFRunLoopRef)aRunLoop forMode:(CFStringRef)aMode
{
CFReadStreamScheduleWithRunLoop((CFReadStreamRef)stream, aRunLoop, aMode);
}

- (BOOL)setCFClientFlags:(CFOptionFlags)inFlags callback:(CFReadStreamClientCallBack)inCallback context:(CFStreamClientContext *)inContext
{
if (inCallback != NULL) {
requestedEvents = inFlags;
copiedCallback = inCallback;
memcpy(&copiedContext, inContext, sizeof(CFStreamClientContext));

if (copiedContext.info && copiedContext.retain) {
copiedContext.retain(copiedContext.info);
}
}
else {
requestedEvents = kCFStreamEventNone;
copiedCallback = NULL;
if (copiedContext.info && copiedContext.release) {
copiedContext.release(copiedContext.info);
}

memset(&copiedContext, 0, sizeof(CFStreamClientContext));
}

return YES;
}

- (void)unscheduleFromCFRunLoop:(CFRunLoopRef)aRunLoop forMode:(CFStringRef)aMode
{
CFReadStreamUnscheduleFromRunLoop((CFReadStreamRef)stream, aRunLoop, aMode);
}

#pragma mark - NSStreamDelegate methods

- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
assert(aStream == stream);

switch (eventCode) {
case NSStreamEventOpenCompleted:
if (requestedEvents & kCFStreamEventOpenCompleted) {
copiedCallback((CFReadStreamRef)self,
kCFStreamEventOpenCompleted,
copiedContext.info);
}
break;

case NSStreamEventHasBytesAvailable:
if (requestedEvents & kCFStreamEventHasBytesAvailable) {
copiedCallback((CFReadStreamRef)self,
kCFStreamEventHasBytesAvailable,
copiedContext.info);
}
break;

case NSStreamEventErrorOccurred:
if (requestedEvents & kCFStreamEventErrorOccurred) {
copiedCallback((CFReadStreamRef)self,
kCFStreamEventErrorOccurred,
copiedContext.info);
}
break;

case NSStreamEventEndEncountered:
if (requestedEvents & kCFStreamEventEndEncountered) {
copiedCallback((CFReadStreamRef)self,
kCFStreamEventEndEncountered,
copiedContext.info);
}
break;

case NSStreamEventHasSpaceAvailable:
// This doesn't make sense for a read stream
break;

default:
break;
}
}

// If we get asked to perform a method we don't have (probably internal ones),
// we'll just forward the message to our stream

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
return [stream methodSignatureForSelector:aSelector];
return [stream methodSignatureForSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
[anInvocation invokeWithTarget:stream];
[anInvocation invokeWithTarget:stream];
}

@synthesize stream;
@synthesize request;
@end
6 changes: 3 additions & 3 deletions Mac Sample/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -358,15 +358,15 @@ - (void)tableViewDataFetchFinished:(ASIHTTPRequest *)request

- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView
{
return [[self rowData] count];
return (NSInteger)[[self rowData] count];
}

- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
{
if ([[aTableColumn identifier] isEqualToString:@"image"]) {
return [[[self rowData] objectAtIndex:rowIndex] objectForKey:@"image"];
return [[[self rowData] objectAtIndex:(NSUInteger)rowIndex] objectForKey:@"image"];
} else {
return [[[self rowData] objectAtIndex:rowIndex] objectForKey:@"description"];
return [[[self rowData] objectAtIndex:(NSUInteger)rowIndex] objectForKey:@"description"];
}
}

Expand Down
4 changes: 2 additions & 2 deletions Mac.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,7 @@
GCC_OPTIMIZATION_LEVEL = 0;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.6;
MACOSX_DEPLOYMENT_TARGET = 10.5;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
Expand All @@ -726,7 +726,7 @@
GCC_C_LANGUAGE_STANDARD = "compiler-default";
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.6;
MACOSX_DEPLOYMENT_TARGET = 10.5;
SDKROOT = macosx;
};
name = Release;
Expand Down
Loading