Showing
7 changed files
with
159 additions
and
114 deletions
| @@ -50,6 +50,11 @@ | @@ -50,6 +50,11 @@ | ||
| 50 | 50 | ||
| 51 | - (void)buildPostBody | 51 | - (void)buildPostBody |
| 52 | { | 52 | { |
| 53 | + if (!postData && ! fileData) { | ||
| 54 | + [super buildPostBody]; | ||
| 55 | + return; | ||
| 56 | + } | ||
| 57 | + | ||
| 53 | NSMutableData *body = [[[NSMutableData alloc] init] autorelease]; | 58 | NSMutableData *body = [[[NSMutableData alloc] init] autorelease]; |
| 54 | 59 | ||
| 55 | // Set your own boundary string only if really obsessive. We don't bother to check if post data contains the boundary, since it's pretty unlikely that it does. | 60 | // Set your own boundary string only if really obsessive. We don't bother to check if post data contains the boundary, since it's pretty unlikely that it does. |
| @@ -10,6 +10,7 @@ | @@ -10,6 +10,7 @@ | ||
| 10 | // Portions are based on the ImageClient example from Apple: | 10 | // Portions are based on the ImageClient example from Apple: |
| 11 | // See: http://developer.apple.com/samplecode/ImageClient/listing37.html | 11 | // See: http://developer.apple.com/samplecode/ImageClient/listing37.html |
| 12 | 12 | ||
| 13 | +#import <Cocoa/Cocoa.h> | ||
| 13 | 14 | ||
| 14 | @interface ASIHTTPRequest : NSOperation { | 15 | @interface ASIHTTPRequest : NSOperation { |
| 15 | 16 | ||
| @@ -93,18 +94,18 @@ | @@ -93,18 +94,18 @@ | ||
| 93 | int responseStatusCode; | 94 | int responseStatusCode; |
| 94 | 95 | ||
| 95 | //Size of the response | 96 | //Size of the response |
| 96 | - unsigned int contentLength; | 97 | + unsigned long long contentLength; |
| 97 | 98 | ||
| 98 | //Size of the POST payload | 99 | //Size of the POST payload |
| 99 | - unsigned int postLength; | 100 | + unsigned long long postLength; |
| 100 | 101 | ||
| 101 | //The total amount of downloaded data | 102 | //The total amount of downloaded data |
| 102 | - unsigned int totalBytesRead; | 103 | + unsigned long long totalBytesRead; |
| 103 | 104 | ||
| 104 | //Last amount of data read (used for incrementing progress) | 105 | //Last amount of data read (used for incrementing progress) |
| 105 | - unsigned int lastBytesRead; | 106 | + unsigned long long lastBytesRead; |
| 106 | //Last amount of data sent (used for incrementing progress) | 107 | //Last amount of data sent (used for incrementing progress) |
| 107 | - unsigned int lastBytesSent; | 108 | + unsigned long long lastBytesSent; |
| 108 | 109 | ||
| 109 | //Realm for authentication when credentials are required | 110 | //Realm for authentication when credentials are required |
| 110 | NSString *authenticationRealm; | 111 | NSString *authenticationRealm; |
| @@ -112,6 +113,9 @@ | @@ -112,6 +113,9 @@ | ||
| 112 | //This lock will block the request until the delegate supplies authentication info | 113 | //This lock will block the request until the delegate supplies authentication info |
| 113 | NSConditionLock *authenticationLock; | 114 | NSConditionLock *authenticationLock; |
| 114 | 115 | ||
| 116 | + //This lock prevents the operation from being cancelled at an inopportune moment | ||
| 117 | + NSLock *cancelledLock; | ||
| 118 | + | ||
| 115 | //Called on the delegate when the request completes successfully | 119 | //Called on the delegate when the request completes successfully |
| 116 | SEL didFinishSelector; | 120 | SEL didFinishSelector; |
| 117 | 121 | ||
| @@ -128,7 +132,7 @@ | @@ -128,7 +132,7 @@ | ||
| 128 | NSAutoreleasePool *pool; | 132 | NSAutoreleasePool *pool; |
| 129 | 133 | ||
| 130 | // Will be YES when a HEAD request will handle the content-length before this request starts | 134 | // Will be YES when a HEAD request will handle the content-length before this request starts |
| 131 | - BOOL useCachedContentLength; | 135 | + BOOL shouldResetProgressIndicators; |
| 132 | 136 | ||
| 133 | // Used by HEAD requests when showAccurateProgress is YES to preset the content-length for this request | 137 | // Used by HEAD requests when showAccurateProgress is YES to preset the content-length for this request |
| 134 | ASIHTTPRequest *mainRequest; | 138 | ASIHTTPRequest *mainRequest; |
| @@ -177,9 +181,9 @@ | @@ -177,9 +181,9 @@ | ||
| 177 | 181 | ||
| 178 | // Called on main thread to update progress delegates | 182 | // Called on main thread to update progress delegates |
| 179 | - (void)updateProgressIndicators; | 183 | - (void)updateProgressIndicators; |
| 180 | -- (void)resetUploadProgress:(NSNumber *)max; | 184 | +- (void)resetUploadProgress:(unsigned long long)value; |
| 181 | - (void)updateUploadProgress; | 185 | - (void)updateUploadProgress; |
| 182 | -- (void)resetDownloadProgress:(NSNumber *)max; | 186 | +- (void)resetDownloadProgress:(unsigned long long)value; |
| 183 | - (void)updateDownloadProgress; | 187 | - (void)updateDownloadProgress; |
| 184 | 188 | ||
| 185 | // Called when authorisation is needed, as we only find out we don't have permission to something when the upload is complete | 189 | // Called when authorisation is needed, as we only find out we don't have permission to something when the upload is complete |
| @@ -279,10 +283,10 @@ | @@ -279,10 +283,10 @@ | ||
| 279 | @property (assign) NSTimeInterval timeOutSeconds; | 283 | @property (assign) NSTimeInterval timeOutSeconds; |
| 280 | @property (retain) NSString *requestMethod; | 284 | @property (retain) NSString *requestMethod; |
| 281 | @property (retain,setter=setPostBody:) NSData *postBody; | 285 | @property (retain,setter=setPostBody:) NSData *postBody; |
| 282 | -@property (assign) unsigned int contentLength; | 286 | +@property (assign) unsigned long long contentLength; |
| 283 | -@property (assign) unsigned int postLength; | 287 | +@property (assign) unsigned long long postLength; |
| 284 | -@property (assign) BOOL useCachedContentLength; | 288 | +@property (assign) BOOL shouldResetProgressIndicators; |
| 285 | @property (retain) ASIHTTPRequest *mainRequest; | 289 | @property (retain) ASIHTTPRequest *mainRequest; |
| 286 | @property (assign) BOOL showAccurateProgress; | 290 | @property (assign) BOOL showAccurateProgress; |
| 287 | -@property (assign,readonly) unsigned int totalBytesRead; | 291 | +@property (assign,readonly) unsigned long long totalBytesRead; |
| 288 | @end | 292 | @end |
| @@ -33,7 +33,7 @@ static void ReadStreamClientCallBack(CFReadStreamRef readStream, CFStreamEventTy | @@ -33,7 +33,7 @@ static void ReadStreamClientCallBack(CFReadStreamRef readStream, CFStreamEventTy | ||
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | // This lock prevents the operation from being cancelled while it is trying to update the progress, and vice versa | 35 | // This lock prevents the operation from being cancelled while it is trying to update the progress, and vice versa |
| 36 | -static NSLock *progressLock; | 36 | +static NSRecursiveLock *progressLock; |
| 37 | 37 | ||
| 38 | @implementation ASIHTTPRequest | 38 | @implementation ASIHTTPRequest |
| 39 | 39 | ||
| @@ -41,9 +41,9 @@ static NSLock *progressLock; | @@ -41,9 +41,9 @@ static NSLock *progressLock; | ||
| 41 | 41 | ||
| 42 | #pragma mark init / dealloc | 42 | #pragma mark init / dealloc |
| 43 | 43 | ||
| 44 | -- (void)initialize | 44 | ++ (void)initialize |
| 45 | { | 45 | { |
| 46 | - progressLock = [[NSLock alloc] init]; | 46 | + progressLock = [[NSRecursiveLock alloc] init]; |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | - (id)initWithURL:(NSURL *)newURL | 49 | - (id)initWithURL:(NSURL *)newURL |
| @@ -52,7 +52,7 @@ static NSLock *progressLock; | @@ -52,7 +52,7 @@ static NSLock *progressLock; | ||
| 52 | [self setRequestMethod:@"GET"]; | 52 | [self setRequestMethod:@"GET"]; |
| 53 | lastBytesSent = 0; | 53 | lastBytesSent = 0; |
| 54 | showAccurateProgress = YES; | 54 | showAccurateProgress = YES; |
| 55 | - useCachedContentLength = NO; | 55 | + shouldResetProgressIndicators = YES; |
| 56 | updatedProgress = NO; | 56 | updatedProgress = NO; |
| 57 | mainRequest = nil; | 57 | mainRequest = nil; |
| 58 | username = nil; | 58 | username = nil; |
| @@ -74,6 +74,7 @@ static NSLock *progressLock; | @@ -74,6 +74,7 @@ static NSLock *progressLock; | ||
| 74 | didFailSelector = @selector(requestFailed:); | 74 | didFailSelector = @selector(requestFailed:); |
| 75 | delegate = nil; | 75 | delegate = nil; |
| 76 | url = [newURL retain]; | 76 | url = [newURL retain]; |
| 77 | + cancelledLock = [[NSLock alloc] init]; | ||
| 77 | return self; | 78 | return self; |
| 78 | } | 79 | } |
| 79 | 80 | ||
| @@ -105,6 +106,7 @@ static NSLock *progressLock; | @@ -105,6 +106,7 @@ static NSLock *progressLock; | ||
| 105 | [receivedData release]; | 106 | [receivedData release]; |
| 106 | [responseHeaders release]; | 107 | [responseHeaders release]; |
| 107 | [requestMethod release]; | 108 | [requestMethod release]; |
| 109 | + [cancelledLock release]; | ||
| 108 | [super dealloc]; | 110 | [super dealloc]; |
| 109 | } | 111 | } |
| 110 | 112 | ||
| @@ -143,17 +145,15 @@ static NSLock *progressLock; | @@ -143,17 +145,15 @@ static NSLock *progressLock; | ||
| 143 | return complete; | 145 | return complete; |
| 144 | } | 146 | } |
| 145 | 147 | ||
| 148 | + | ||
| 146 | - (void)cancel | 149 | - (void)cancel |
| 147 | { | 150 | { |
| 148 | - [progressLock lock]; | 151 | + [self failWithProblem:@"The request was cancelled"]; |
| 152 | + [self cancelLoad]; | ||
| 153 | + complete = YES; | ||
| 149 | [super cancel]; | 154 | [super cancel]; |
| 150 | - [progressLock unlock]; | ||
| 151 | } | 155 | } |
| 152 | 156 | ||
| 153 | -- (int)totalBytesRead | ||
| 154 | -{ | ||
| 155 | - return totalBytesRead; | ||
| 156 | -} | ||
| 157 | 157 | ||
| 158 | // Call this method to get the recieved data as an NSString. Don't use for Binary data! | 158 | // Call this method to get the recieved data as an NSString. Don't use for Binary data! |
| 159 | - (NSString *)dataString | 159 | - (NSString *)dataString |
| @@ -226,8 +226,8 @@ static NSLock *progressLock; | @@ -226,8 +226,8 @@ static NSLock *progressLock; | ||
| 226 | CFHTTPMessageSetHeaderFieldValue(request, (CFStringRef)header, (CFStringRef)[requestHeaders objectForKey:header]); | 226 | CFHTTPMessageSetHeaderFieldValue(request, (CFStringRef)header, (CFStringRef)[requestHeaders objectForKey:header]); |
| 227 | } | 227 | } |
| 228 | 228 | ||
| 229 | - | 229 | + //NSData *d = (NSData *)CFHTTPMessageCopySerializedMessage(request); |
| 230 | - | 230 | + //NSLog(@"%@",[[[NSString alloc] initWithBytes:[d bytes] length:[d length] encoding:NSUTF8StringEncoding] autorelease]); |
| 231 | 231 | ||
| 232 | 232 | ||
| 233 | // If this is a post request and we have data to send, add it to the request | 233 | // If this is a post request and we have data to send, add it to the request |
| @@ -243,6 +243,13 @@ static NSLock *progressLock; | @@ -243,6 +243,13 @@ static NSLock *progressLock; | ||
| 243 | // Start the request | 243 | // Start the request |
| 244 | - (void)loadRequest | 244 | - (void)loadRequest |
| 245 | { | 245 | { |
| 246 | + [cancelledLock lock]; | ||
| 247 | + | ||
| 248 | + if ([self isCancelled]) { | ||
| 249 | + [cancelledLock unlock]; | ||
| 250 | + return; | ||
| 251 | + } | ||
| 252 | + | ||
| 246 | CFRunLoopAddCommonMode(CFRunLoopGetCurrent(),ASIHTTPRequestRunMode); | 253 | CFRunLoopAddCommonMode(CFRunLoopGetCurrent(),ASIHTTPRequestRunMode); |
| 247 | 254 | ||
| 248 | [authenticationLock release]; | 255 | [authenticationLock release]; |
| @@ -258,7 +265,7 @@ static NSLock *progressLock; | @@ -258,7 +265,7 @@ static NSLock *progressLock; | ||
| 258 | } | 265 | } |
| 259 | 266 | ||
| 260 | lastBytesSent = 0; | 267 | lastBytesSent = 0; |
| 261 | - if (!useCachedContentLength) { | 268 | + if (shouldResetProgressIndicators) { |
| 262 | contentLength = 0; | 269 | contentLength = 0; |
| 263 | } | 270 | } |
| 264 | [self setResponseHeaders:nil]; | 271 | [self setResponseHeaders:nil]; |
| @@ -267,6 +274,7 @@ static NSLock *progressLock; | @@ -267,6 +274,7 @@ static NSLock *progressLock; | ||
| 267 | // Create the stream for the request. | 274 | // Create the stream for the request. |
| 268 | readStream = CFReadStreamCreateForStreamedHTTPRequest(kCFAllocatorDefault, request,readStream); | 275 | readStream = CFReadStreamCreateForStreamedHTTPRequest(kCFAllocatorDefault, request,readStream); |
| 269 | if (!readStream) { | 276 | if (!readStream) { |
| 277 | + [cancelledLock unlock]; | ||
| 270 | [self failWithProblem:@"Unable to create read stream"]; | 278 | [self failWithProblem:@"Unable to create read stream"]; |
| 271 | return; | 279 | return; |
| 272 | } | 280 | } |
| @@ -276,6 +284,7 @@ static NSLock *progressLock; | @@ -276,6 +284,7 @@ static NSLock *progressLock; | ||
| 276 | if (!CFReadStreamSetClient(readStream, kNetworkEvents, ReadStreamClientCallBack, &ctxt)) { | 284 | if (!CFReadStreamSetClient(readStream, kNetworkEvents, ReadStreamClientCallBack, &ctxt)) { |
| 277 | CFRelease(readStream); | 285 | CFRelease(readStream); |
| 278 | readStream = NULL; | 286 | readStream = NULL; |
| 287 | + [cancelledLock unlock]; | ||
| 279 | [self failWithProblem:@"Unable to setup read stream"]; | 288 | [self failWithProblem:@"Unable to setup read stream"]; |
| 280 | return; | 289 | return; |
| 281 | } | 290 | } |
| @@ -289,14 +298,23 @@ static NSLock *progressLock; | @@ -289,14 +298,23 @@ static NSLock *progressLock; | ||
| 289 | CFReadStreamUnscheduleFromRunLoop(readStream, CFRunLoopGetCurrent(), ASIHTTPRequestRunMode); | 298 | CFReadStreamUnscheduleFromRunLoop(readStream, CFRunLoopGetCurrent(), ASIHTTPRequestRunMode); |
| 290 | CFRelease(readStream); | 299 | CFRelease(readStream); |
| 291 | readStream = NULL; | 300 | readStream = NULL; |
| 301 | + [cancelledLock unlock]; | ||
| 292 | [self failWithProblem:@"Unable to start http connection"]; | 302 | [self failWithProblem:@"Unable to start http connection"]; |
| 293 | return; | 303 | return; |
| 294 | } | 304 | } |
| 305 | + [cancelledLock unlock]; | ||
| 295 | 306 | ||
| 296 | - if (uploadProgressDelegate) { | 307 | + |
| 297 | - [self performSelectorOnMainThread:@selector(resetUploadProgress:) withObject:[NSNumber numberWithDouble:postLength] waitUntilDone:YES]; | 308 | + if (uploadProgressDelegate && shouldResetProgressIndicators) { |
| 309 | + double amount = 1; | ||
| 310 | + if (showAccurateProgress) { | ||
| 311 | + amount = postLength; | ||
| 312 | + } | ||
| 313 | + [self resetUploadProgress:amount]; | ||
| 298 | } | 314 | } |
| 299 | 315 | ||
| 316 | + | ||
| 317 | + | ||
| 300 | // Record when the request started, so we can timeout if nothing happens | 318 | // Record when the request started, so we can timeout if nothing happens |
| 301 | [self setLastActivityTime:[NSDate date]]; | 319 | [self setLastActivityTime:[NSDate date]]; |
| 302 | 320 | ||
| @@ -307,9 +325,11 @@ static NSLock *progressLock; | @@ -307,9 +325,11 @@ static NSLock *progressLock; | ||
| 307 | [pool release]; | 325 | [pool release]; |
| 308 | pool = [[NSAutoreleasePool alloc] init]; | 326 | pool = [[NSAutoreleasePool alloc] init]; |
| 309 | 327 | ||
| 328 | + NSDate *now = [NSDate new]; | ||
| 329 | + | ||
| 310 | // See if we need to timeout | 330 | // See if we need to timeout |
| 311 | if (lastActivityTime && timeOutSeconds > 0) { | 331 | if (lastActivityTime && timeOutSeconds > 0) { |
| 312 | - if ([[NSDate date] timeIntervalSinceDate:lastActivityTime] > timeOutSeconds) { | 332 | + if ([now timeIntervalSinceDate:lastActivityTime] > timeOutSeconds) { |
| 313 | [self failWithProblem:@"Request timed out"]; | 333 | [self failWithProblem:@"Request timed out"]; |
| 314 | [self cancelLoad]; | 334 | [self cancelLoad]; |
| 315 | complete = YES; | 335 | complete = YES; |
| @@ -324,10 +344,12 @@ static NSLock *progressLock; | @@ -324,10 +344,12 @@ static NSLock *progressLock; | ||
| 324 | complete = YES; | 344 | complete = YES; |
| 325 | break; | 345 | break; |
| 326 | } | 346 | } |
| 327 | - [self performSelectorOnMainThread:@selector(updateProgressIndicators) withObject:nil waitUntilDone:YES]; | 347 | + |
| 348 | + [self updateProgressIndicators]; | ||
| 328 | 349 | ||
| 329 | //This thread should wait for 1/4 second for the stream to do something. We'll stop early if it does. | 350 | //This thread should wait for 1/4 second for the stream to do something. We'll stop early if it does. |
| 330 | CFRunLoopRunInMode(ASIHTTPRequestRunMode,0.25,YES); | 351 | CFRunLoopRunInMode(ASIHTTPRequestRunMode,0.25,YES); |
| 352 | + [now release]; | ||
| 331 | } | 353 | } |
| 332 | 354 | ||
| 333 | [pool release]; | 355 | [pool release]; |
| @@ -337,6 +359,7 @@ static NSLock *progressLock; | @@ -337,6 +359,7 @@ static NSLock *progressLock; | ||
| 337 | // Cancel loading and clean up | 359 | // Cancel loading and clean up |
| 338 | - (void)cancelLoad | 360 | - (void)cancelLoad |
| 339 | { | 361 | { |
| 362 | + [cancelledLock lock]; | ||
| 340 | if (readStream) { | 363 | if (readStream) { |
| 341 | CFReadStreamClose(readStream); | 364 | CFReadStreamClose(readStream); |
| 342 | CFReadStreamSetClient(readStream, kCFStreamEventNone, NULL, NULL); | 365 | CFReadStreamSetClient(readStream, kCFStreamEventNone, NULL, NULL); |
| @@ -355,6 +378,7 @@ static NSLock *progressLock; | @@ -355,6 +378,7 @@ static NSLock *progressLock; | ||
| 355 | } | 378 | } |
| 356 | 379 | ||
| 357 | [self setResponseHeaders:nil]; | 380 | [self setResponseHeaders:nil]; |
| 381 | + [cancelledLock unlock]; | ||
| 358 | } | 382 | } |
| 359 | 383 | ||
| 360 | 384 | ||
| @@ -364,9 +388,9 @@ static NSLock *progressLock; | @@ -364,9 +388,9 @@ static NSLock *progressLock; | ||
| 364 | 388 | ||
| 365 | - (void)updateProgressIndicators | 389 | - (void)updateProgressIndicators |
| 366 | { | 390 | { |
| 391 | + | ||
| 367 | //Only update progress if this isn't a HEAD request used to preset the content-length | 392 | //Only update progress if this isn't a HEAD request used to preset the content-length |
| 368 | if (!mainRequest) { | 393 | if (!mainRequest) { |
| 369 | - | ||
| 370 | if (showAccurateProgress || (complete && !updatedProgress)) { | 394 | if (showAccurateProgress || (complete && !updatedProgress)) { |
| 371 | [self updateUploadProgress]; | 395 | [self updateUploadProgress]; |
| 372 | [self updateDownloadProgress]; | 396 | [self updateDownloadProgress]; |
| @@ -411,17 +435,11 @@ static NSLock *progressLock; | @@ -411,17 +435,11 @@ static NSLock *progressLock; | ||
| 411 | } | 435 | } |
| 412 | 436 | ||
| 413 | 437 | ||
| 414 | -- (void)resetUploadProgress:(NSNumber *)max | 438 | +- (void)resetUploadProgress:(unsigned long long)value |
| 415 | { | 439 | { |
| 416 | [progressLock lock]; | 440 | [progressLock lock]; |
| 417 | - if ([self isCancelled]) { | ||
| 418 | - [progressLock unlock]; | ||
| 419 | - return; | ||
| 420 | - } | ||
| 421 | - | ||
| 422 | //We're using a progress queue or compatible controller to handle progress | 441 | //We're using a progress queue or compatible controller to handle progress |
| 423 | if ([uploadProgressDelegate respondsToSelector:@selector(incrementUploadSizeBy:)]) { | 442 | if ([uploadProgressDelegate respondsToSelector:@selector(incrementUploadSizeBy:)]) { |
| 424 | - int value = [max intValue]; | ||
| 425 | SEL selector = @selector(incrementUploadSizeBy:); | 443 | SEL selector = @selector(incrementUploadSizeBy:); |
| 426 | NSMethodSignature *signature = [[uploadProgressDelegate class] instanceMethodSignatureForSelector:selector]; | 444 | NSMethodSignature *signature = [[uploadProgressDelegate class] instanceMethodSignatureForSelector:selector]; |
| 427 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; | 445 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; |
| @@ -437,20 +455,21 @@ static NSLock *progressLock; | @@ -437,20 +455,21 @@ static NSLock *progressLock; | ||
| 437 | 455 | ||
| 438 | - (void)updateUploadProgress | 456 | - (void)updateUploadProgress |
| 439 | { | 457 | { |
| 440 | - [progressLock lock]; | 458 | + [cancelledLock lock]; |
| 441 | if ([self isCancelled]) { | 459 | if ([self isCancelled]) { |
| 442 | - [progressLock unlock]; | ||
| 443 | return; | 460 | return; |
| 444 | } | 461 | } |
| 445 | - | 462 | + unsigned long long byteCount = [[(NSNumber *)CFReadStreamCopyProperty (readStream, kCFStreamPropertyHTTPRequestBytesWrittenCount) autorelease] unsignedLongLongValue]; |
| 463 | + [cancelledLock unlock]; | ||
| 464 | + if (byteCount > lastBytesSent) { | ||
| 446 | [self setLastActivityTime:[NSDate date]]; | 465 | [self setLastActivityTime:[NSDate date]]; |
| 466 | + } | ||
| 447 | 467 | ||
| 448 | - unsigned int byteCount = [[(NSNumber *)CFReadStreamCopyProperty (readStream, kCFStreamPropertyHTTPRequestBytesWrittenCount) autorelease] unsignedIntValue]; | ||
| 449 | if (uploadProgressDelegate) { | 468 | if (uploadProgressDelegate) { |
| 450 | 469 | ||
| 451 | //We're using a progress queue or compatible controller to handle progress | 470 | //We're using a progress queue or compatible controller to handle progress |
| 452 | if ([uploadProgressDelegate respondsToSelector:@selector(incrementUploadProgressBy:)]) { | 471 | if ([uploadProgressDelegate respondsToSelector:@selector(incrementUploadProgressBy:)]) { |
| 453 | - int value = 0; | 472 | + unsigned long long value = 0; |
| 454 | if (showAccurateProgress) { | 473 | if (showAccurateProgress) { |
| 455 | value = byteCount-lastBytesSent; | 474 | value = byteCount-lastBytesSent; |
| 456 | } else { | 475 | } else { |
| @@ -473,22 +492,15 @@ static NSLock *progressLock; | @@ -473,22 +492,15 @@ static NSLock *progressLock; | ||
| 473 | 492 | ||
| 474 | } | 493 | } |
| 475 | lastBytesSent = byteCount; | 494 | lastBytesSent = byteCount; |
| 476 | - [progressLock unlock]; | 495 | + |
| 477 | } | 496 | } |
| 478 | 497 | ||
| 479 | 498 | ||
| 480 | -- (void)resetDownloadProgress:(NSNumber *)max | 499 | +- (void)resetDownloadProgress:(unsigned long long)value |
| 481 | { | 500 | { |
| 482 | [progressLock lock]; | 501 | [progressLock lock]; |
| 483 | - if ([self isCancelled]) { | ||
| 484 | - [progressLock unlock]; | ||
| 485 | - return; | ||
| 486 | - } | ||
| 487 | - | ||
| 488 | - | ||
| 489 | //We're using a progress queue or compatible controller to handle progress | 502 | //We're using a progress queue or compatible controller to handle progress |
| 490 | if ([downloadProgressDelegate respondsToSelector:@selector(incrementDownloadSizeBy:)]) { | 503 | if ([downloadProgressDelegate respondsToSelector:@selector(incrementDownloadSizeBy:)]) { |
| 491 | - int value = [max intValue]; | ||
| 492 | SEL selector = @selector(incrementDownloadSizeBy:); | 504 | SEL selector = @selector(incrementDownloadSizeBy:); |
| 493 | NSMethodSignature *signature = [[downloadProgressDelegate class] instanceMethodSignatureForSelector:selector]; | 505 | NSMethodSignature *signature = [[downloadProgressDelegate class] instanceMethodSignatureForSelector:selector]; |
| 494 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; | 506 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; |
| @@ -496,6 +508,7 @@ static NSLock *progressLock; | @@ -496,6 +508,7 @@ static NSLock *progressLock; | ||
| 496 | [invocation setSelector:selector]; | 508 | [invocation setSelector:selector]; |
| 497 | [invocation setArgument:&value atIndex:2]; | 509 | [invocation setArgument:&value atIndex:2]; |
| 498 | [invocation invoke]; | 510 | [invocation invoke]; |
| 511 | + | ||
| 499 | } else { | 512 | } else { |
| 500 | [ASIHTTPRequest setProgress:0 forProgressIndicator:downloadProgressDelegate]; | 513 | [ASIHTTPRequest setProgress:0 forProgressIndicator:downloadProgressDelegate]; |
| 501 | } | 514 | } |
| @@ -504,30 +517,33 @@ static NSLock *progressLock; | @@ -504,30 +517,33 @@ static NSLock *progressLock; | ||
| 504 | 517 | ||
| 505 | - (void)updateDownloadProgress | 518 | - (void)updateDownloadProgress |
| 506 | { | 519 | { |
| 507 | - [progressLock lock]; | 520 | + unsigned long long bytesReadSoFar = totalBytesRead; |
| 508 | - if ([self isCancelled]) { | 521 | + |
| 509 | - [progressLock unlock]; | 522 | + //We won't update download progress until we've examined the headers, since we might need to authenticate |
| 510 | - return; | 523 | + if (responseHeaders) { |
| 511 | - } | ||
| 512 | 524 | ||
| 525 | + if (bytesReadSoFar > lastBytesRead) { | ||
| 513 | [self setLastActivityTime:[NSDate date]]; | 526 | [self setLastActivityTime:[NSDate date]]; |
| 527 | + } | ||
| 528 | + | ||
| 529 | + if (downloadProgressDelegate) { | ||
| 514 | 530 | ||
| 515 | - //We won't update downlaod progress until we've examined the headers, since we might need to authenticate | ||
| 516 | - if (downloadProgressDelegate && responseHeaders) { | ||
| 517 | 531 | ||
| 518 | //We're using a progress queue or compatible controller to handle progress | 532 | //We're using a progress queue or compatible controller to handle progress |
| 519 | if ([downloadProgressDelegate respondsToSelector:@selector(incrementDownloadProgressBy:)]) { | 533 | if ([downloadProgressDelegate respondsToSelector:@selector(incrementDownloadProgressBy:)]) { |
| 520 | 534 | ||
| 521 | NSAutoreleasePool *thePool = [[NSAutoreleasePool alloc] init]; | 535 | NSAutoreleasePool *thePool = [[NSAutoreleasePool alloc] init]; |
| 522 | 536 | ||
| 523 | - int value = 0; | 537 | + unsigned long long value = 0; |
| 524 | if (showAccurateProgress) { | 538 | if (showAccurateProgress) { |
| 525 | - value = totalBytesRead-lastBytesRead; | 539 | + value = bytesReadSoFar-lastBytesRead; |
| 526 | } else { | 540 | } else { |
| 527 | value = 1; | 541 | value = 1; |
| 528 | updatedProgress = YES; | 542 | updatedProgress = YES; |
| 529 | } | 543 | } |
| 530 | 544 | ||
| 545 | + | ||
| 546 | + | ||
| 531 | SEL selector = @selector(incrementDownloadProgressBy:); | 547 | SEL selector = @selector(incrementDownloadProgressBy:); |
| 532 | NSMethodSignature *signature = [[downloadProgressDelegate class] instanceMethodSignatureForSelector:selector]; | 548 | NSMethodSignature *signature = [[downloadProgressDelegate class] instanceMethodSignatureForSelector:selector]; |
| 533 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; | 549 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; |
| @@ -540,26 +556,22 @@ static NSLock *progressLock; | @@ -540,26 +556,22 @@ static NSLock *progressLock; | ||
| 540 | 556 | ||
| 541 | //We aren't using a queue, we should just set progress of the indicator to 0 | 557 | //We aren't using a queue, we should just set progress of the indicator to 0 |
| 542 | } else if (contentLength > 0) { | 558 | } else if (contentLength > 0) { |
| 543 | - [ASIHTTPRequest setProgress:(double)(totalBytesRead/contentLength) forProgressIndicator:downloadProgressDelegate]; | 559 | + [ASIHTTPRequest setProgress:(double)(bytesReadSoFar/contentLength) forProgressIndicator:downloadProgressDelegate]; |
| 560 | + } | ||
| 544 | } | 561 | } |
| 545 | 562 | ||
| 546 | - lastBytesRead = totalBytesRead; | 563 | + lastBytesRead = bytesReadSoFar; |
| 547 | } | 564 | } |
| 548 | - [progressLock unlock]; | 565 | + |
| 549 | } | 566 | } |
| 550 | 567 | ||
| 551 | -(void)removeUploadProgressSoFar | 568 | -(void)removeUploadProgressSoFar |
| 552 | { | 569 | { |
| 553 | - [progressLock lock]; | ||
| 554 | - if ([self isCancelled]) { | ||
| 555 | - [progressLock unlock]; | ||
| 556 | - return; | ||
| 557 | - } | ||
| 558 | 570 | ||
| 559 | //We're using a progress queue or compatible controller to handle progress | 571 | //We're using a progress queue or compatible controller to handle progress |
| 560 | - if ([uploadProgressDelegate respondsToSelector:@selector(incrementUploadProgressBy:)]) { | 572 | + if ([uploadProgressDelegate respondsToSelector:@selector(decrementUploadProgressBy:)]) { |
| 561 | - int value = 0-lastBytesSent; | 573 | + unsigned long long value = 0-lastBytesSent; |
| 562 | - SEL selector = @selector(incrementUploadProgressBy:); | 574 | + SEL selector = @selector(decrementUploadProgressBy:); |
| 563 | NSMethodSignature *signature = [[uploadProgressDelegate class] instanceMethodSignatureForSelector:selector]; | 575 | NSMethodSignature *signature = [[uploadProgressDelegate class] instanceMethodSignatureForSelector:selector]; |
| 564 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; | 576 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; |
| 565 | [invocation setTarget:uploadProgressDelegate]; | 577 | [invocation setTarget:uploadProgressDelegate]; |
| @@ -571,7 +583,6 @@ static NSLock *progressLock; | @@ -571,7 +583,6 @@ static NSLock *progressLock; | ||
| 571 | } else { | 583 | } else { |
| 572 | [ASIHTTPRequest setProgress:0 forProgressIndicator:uploadProgressDelegate]; | 584 | [ASIHTTPRequest setProgress:0 forProgressIndicator:uploadProgressDelegate]; |
| 573 | } | 585 | } |
| 574 | - [progressLock unlock]; | ||
| 575 | } | 586 | } |
| 576 | 587 | ||
| 577 | 588 | ||
| @@ -579,8 +590,9 @@ static NSLock *progressLock; | @@ -579,8 +590,9 @@ static NSLock *progressLock; | ||
| 579 | { | 590 | { |
| 580 | 591 | ||
| 581 | SEL selector; | 592 | SEL selector; |
| 593 | + [progressLock lock]; | ||
| 582 | 594 | ||
| 583 | - //Cocoa Touch: UIProgressView | 595 | + // Cocoa Touch: UIProgressView |
| 584 | if ([indicator respondsToSelector:@selector(setProgress:)]) { | 596 | if ([indicator respondsToSelector:@selector(setProgress:)]) { |
| 585 | selector = @selector(setProgress:); | 597 | selector = @selector(setProgress:); |
| 586 | NSMethodSignature *signature = [[indicator class] instanceMethodSignatureForSelector:selector]; | 598 | NSMethodSignature *signature = [[indicator class] instanceMethodSignatureForSelector:selector]; |
| @@ -590,26 +602,28 @@ static NSLock *progressLock; | @@ -590,26 +602,28 @@ static NSLock *progressLock; | ||
| 590 | [invocation setArgument:&progressFloat atIndex:2]; | 602 | [invocation setArgument:&progressFloat atIndex:2]; |
| 591 | [invocation invokeWithTarget:indicator]; | 603 | [invocation invokeWithTarget:indicator]; |
| 592 | 604 | ||
| 605 | + //If we're running in the main thread, update the progress straight away. Otherwise, it's not that urgent | ||
| 606 | + [invocation performSelectorOnMainThread:@selector(invokeWithTarget:) withObject:indicator waitUntilDone:[NSThread isMainThread]]; | ||
| 593 | 607 | ||
| 594 | - //Cocoa: NSProgressIndicator | 608 | + |
| 609 | + // Cocoa: NSProgressIndicator | ||
| 595 | } else if ([indicator respondsToSelector:@selector(setDoubleValue:)]) { | 610 | } else if ([indicator respondsToSelector:@selector(setDoubleValue:)]) { |
| 596 | selector = @selector(setDoubleValue:); | 611 | selector = @selector(setDoubleValue:); |
| 597 | NSMethodSignature *signature = [[indicator class] instanceMethodSignatureForSelector:selector]; | 612 | NSMethodSignature *signature = [[indicator class] instanceMethodSignatureForSelector:selector]; |
| 598 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; | 613 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; |
| 599 | [invocation setSelector:selector]; | 614 | [invocation setSelector:selector]; |
| 600 | [invocation setArgument:&progress atIndex:2]; | 615 | [invocation setArgument:&progress atIndex:2]; |
| 601 | - [invocation invokeWithTarget:indicator]; | ||
| 602 | 616 | ||
| 603 | - //Progress indicator is some other thing that we can't handle | 617 | + //If we're running in the main thread, update the progress straight away. Otherwise, it's not that urgent |
| 604 | - } else { | 618 | + [invocation performSelectorOnMainThread:@selector(invokeWithTarget:) withObject:indicator waitUntilDone:[NSThread isMainThread]]; |
| 605 | - return; | 619 | + |
| 606 | } | 620 | } |
| 621 | + [progressLock unlock]; | ||
| 607 | } | 622 | } |
| 608 | 623 | ||
| 609 | 624 | ||
| 610 | #pragma mark handling request complete / failure | 625 | #pragma mark handling request complete / failure |
| 611 | 626 | ||
| 612 | - | ||
| 613 | // Subclasses can override this method to process the result in the same thread | 627 | // Subclasses can override this method to process the result in the same thread |
| 614 | // If not overidden, it will call the didFinishSelector on the delegate, if one has been setup | 628 | // If not overidden, it will call the didFinishSelector on the delegate, if one has been setup |
| 615 | - (void)requestFinished | 629 | - (void)requestFinished |
| @@ -656,18 +670,15 @@ static NSLock *progressLock; | @@ -656,18 +670,15 @@ static NSLock *progressLock; | ||
| 656 | //We won't reset the download progress delegate if we got an authentication challenge | 670 | //We won't reset the download progress delegate if we got an authentication challenge |
| 657 | if (!isAuthenticationChallenge) { | 671 | if (!isAuthenticationChallenge) { |
| 658 | 672 | ||
| 659 | - //Only check the content length if we haven't already got one (may have been set by an ASINetworkQueue using a previous HEAD request) | ||
| 660 | - if (!useCachedContentLength) { | ||
| 661 | //See if we got a Content-length header | 673 | //See if we got a Content-length header |
| 662 | NSString *cLength = [responseHeaders valueForKey:@"Content-Length"]; | 674 | NSString *cLength = [responseHeaders valueForKey:@"Content-Length"]; |
| 663 | if (cLength) { | 675 | if (cLength) { |
| 664 | - contentLength = CFStringGetDoubleValue((CFStringRef)cLength); | 676 | + contentLength = CFStringGetIntValue((CFStringRef)cLength); |
| 665 | if (mainRequest) { | 677 | if (mainRequest) { |
| 666 | [mainRequest setContentLength:contentLength]; | 678 | [mainRequest setContentLength:contentLength]; |
| 667 | } | 679 | } |
| 668 | - if (downloadProgressDelegate && showAccurateProgress) { | 680 | + if (downloadProgressDelegate && showAccurateProgress && shouldResetProgressIndicators) { |
| 669 | - [self performSelectorOnMainThread:@selector(resetDownloadProgress:) withObject:[NSNumber numberWithDouble:contentLength] waitUntilDone:YES]; | 681 | + [self resetDownloadProgress:contentLength]; |
| 670 | - } | ||
| 671 | } | 682 | } |
| 672 | } | 683 | } |
| 673 | 684 | ||
| @@ -940,12 +951,15 @@ static NSLock *progressLock; | @@ -940,12 +951,15 @@ static NSLock *progressLock; | ||
| 940 | [receivedData appendBytes:buffer length:bytesRead]; | 951 | [receivedData appendBytes:buffer length:bytesRead]; |
| 941 | } | 952 | } |
| 942 | } | 953 | } |
| 954 | + | ||
| 955 | + | ||
| 943 | } | 956 | } |
| 944 | 957 | ||
| 945 | 958 | ||
| 946 | - (void)handleStreamComplete | 959 | - (void)handleStreamComplete |
| 947 | { | 960 | { |
| 948 | 961 | ||
| 962 | + | ||
| 949 | //Try to read the headers (if this is a HEAD request handleBytesAvailable available may not be called) | 963 | //Try to read the headers (if this is a HEAD request handleBytesAvailable available may not be called) |
| 950 | if (!responseHeaders) { | 964 | if (!responseHeaders) { |
| 951 | if ([self readResponseHeadersReturningAuthenticationFailure]) { | 965 | if ([self readResponseHeadersReturningAuthenticationFailure]) { |
| @@ -953,10 +967,10 @@ static NSLock *progressLock; | @@ -953,10 +967,10 @@ static NSLock *progressLock; | ||
| 953 | return; | 967 | return; |
| 954 | } | 968 | } |
| 955 | } | 969 | } |
| 956 | - | 970 | + [progressLock lock]; |
| 957 | - | ||
| 958 | complete = YES; | 971 | complete = YES; |
| 959 | [self updateProgressIndicators]; | 972 | [self updateProgressIndicators]; |
| 973 | + | ||
| 960 | if (readStream) { | 974 | if (readStream) { |
| 961 | CFReadStreamClose(readStream); | 975 | CFReadStreamClose(readStream); |
| 962 | CFReadStreamSetClient(readStream, kCFStreamEventNone, NULL, NULL); | 976 | CFReadStreamSetClient(readStream, kCFStreamEventNone, NULL, NULL); |
| @@ -969,8 +983,9 @@ static NSLock *progressLock; | @@ -969,8 +983,9 @@ static NSLock *progressLock; | ||
| 969 | if (downloadDestinationPath) { | 983 | if (downloadDestinationPath) { |
| 970 | [outputStream close]; | 984 | [outputStream close]; |
| 971 | } | 985 | } |
| 972 | - | 986 | + [progressLock unlock]; |
| 973 | [self requestFinished]; | 987 | [self requestFinished]; |
| 988 | + | ||
| 974 | } | 989 | } |
| 975 | 990 | ||
| 976 | 991 | ||
| @@ -1101,7 +1116,9 @@ static NSLock *progressLock; | @@ -1101,7 +1116,9 @@ static NSLock *progressLock; | ||
| 1101 | @synthesize postBody; | 1116 | @synthesize postBody; |
| 1102 | @synthesize contentLength; | 1117 | @synthesize contentLength; |
| 1103 | @synthesize postLength; | 1118 | @synthesize postLength; |
| 1104 | -@synthesize useCachedContentLength; | 1119 | +@synthesize shouldResetProgressIndicators; |
| 1105 | @synthesize mainRequest; | 1120 | @synthesize mainRequest; |
| 1121 | +@synthesize totalBytesRead; | ||
| 1106 | @synthesize showAccurateProgress; | 1122 | @synthesize showAccurateProgress; |
| 1123 | +@synthesize totalBytesRead; | ||
| 1107 | @end | 1124 | @end |
| @@ -109,8 +109,9 @@ | @@ -109,8 +109,9 @@ | ||
| 109 | ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease]; | 109 | ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease]; |
| 110 | [request setDownloadProgressDelegate:self]; | 110 | [request setDownloadProgressDelegate:self]; |
| 111 | [request start]; | 111 | [request start]; |
| 112 | + | ||
| 112 | BOOL success = (progress == 1); | 113 | BOOL success = (progress == 1); |
| 113 | - STAssertTrue(success,@"Failed to properly increment download progress"); | 114 | + STAssertTrue(success,@"Failed to properly increment download progress %f != 1.0",progress); |
| 114 | } | 115 | } |
| 115 | 116 | ||
| 116 | 117 | ||
| @@ -121,8 +122,9 @@ | @@ -121,8 +122,9 @@ | ||
| 121 | [request setPostBody:[NSMutableData dataWithLength:1024*32]]; | 122 | [request setPostBody:[NSMutableData dataWithLength:1024*32]]; |
| 122 | [request setUploadProgressDelegate:self]; | 123 | [request setUploadProgressDelegate:self]; |
| 123 | [request start]; | 124 | [request start]; |
| 125 | + | ||
| 124 | BOOL success = (progress == 1); | 126 | BOOL success = (progress == 1); |
| 125 | - STAssertTrue(success,@"Failed to properly increment upload progress"); | 127 | + STAssertTrue(success,@"Failed to properly increment upload progress %f != 1.0",progress); |
| 126 | } | 128 | } |
| 127 | 129 | ||
| 128 | 130 |
| @@ -6,7 +6,7 @@ | @@ -6,7 +6,7 @@ | ||
| 6 | // Copyright 2008 All-Seeing Interactive. All rights reserved. | 6 | // Copyright 2008 All-Seeing Interactive. All rights reserved. |
| 7 | // | 7 | // |
| 8 | 8 | ||
| 9 | - | 9 | +#import <Cocoa/Cocoa.h> |
| 10 | 10 | ||
| 11 | @interface ASINetworkQueue : NSOperationQueue { | 11 | @interface ASINetworkQueue : NSOperationQueue { |
| 12 | 12 | ||
| @@ -26,19 +26,19 @@ | @@ -26,19 +26,19 @@ | ||
| 26 | id uploadProgressDelegate; | 26 | id uploadProgressDelegate; |
| 27 | 27 | ||
| 28 | // Total amount uploaded so far for all requests in this queue | 28 | // Total amount uploaded so far for all requests in this queue |
| 29 | - unsigned int uploadProgressBytes; | 29 | + unsigned long long uploadProgressBytes; |
| 30 | 30 | ||
| 31 | // Total amount to be uploaded for all requests in this queue - requests add to this figure as they work out how much data they have to transmit | 31 | // Total amount to be uploaded for all requests in this queue - requests add to this figure as they work out how much data they have to transmit |
| 32 | - unsigned int uploadProgressTotalBytes; | 32 | + unsigned long long uploadProgressTotalBytes; |
| 33 | 33 | ||
| 34 | // Download progress indicator, probably an NSProgressIndicator or UIProgressView | 34 | // Download progress indicator, probably an NSProgressIndicator or UIProgressView |
| 35 | id downloadProgressDelegate; | 35 | id downloadProgressDelegate; |
| 36 | 36 | ||
| 37 | // Total amount downloaded so far for all requests in this queue | 37 | // Total amount downloaded so far for all requests in this queue |
| 38 | - unsigned int downloadProgressBytes; | 38 | + unsigned long long downloadProgressBytes; |
| 39 | 39 | ||
| 40 | // Total amount to be downloaded for all requests in this queue - requests add to this figure as they receive Content-Length headers | 40 | // Total amount to be downloaded for all requests in this queue - requests add to this figure as they receive Content-Length headers |
| 41 | - unsigned int downloadProgressTotalBytes; | 41 | + unsigned long long downloadProgressTotalBytes; |
| 42 | 42 | ||
| 43 | // When YES, the queue will cancel all requests when a request fails. Default is YES | 43 | // When YES, the queue will cancel all requests when a request fails. Default is YES |
| 44 | BOOL shouldCancelAllRequestsOnFailure; | 44 | BOOL shouldCancelAllRequestsOnFailure; |
| @@ -61,16 +61,19 @@ | @@ -61,16 +61,19 @@ | ||
| 61 | - (void)addHEADOperation:(NSOperation *)operation; | 61 | - (void)addHEADOperation:(NSOperation *)operation; |
| 62 | 62 | ||
| 63 | // Called at the start of a request to add on the size of this upload to the total | 63 | // Called at the start of a request to add on the size of this upload to the total |
| 64 | -- (void)incrementUploadSizeBy:(int)bytes; | 64 | +- (void)incrementUploadSizeBy:(unsigned long long)bytes; |
| 65 | 65 | ||
| 66 | // Called during a request when data is written to the upload stream to increment the progress indicator | 66 | // Called during a request when data is written to the upload stream to increment the progress indicator |
| 67 | -- (void)incrementUploadProgressBy:(int)bytes; | 67 | +- (void)incrementUploadProgressBy:(unsigned long long)bytes; |
| 68 | 68 | ||
| 69 | // Called at the start of a request to add on the size of this download to the total | 69 | // Called at the start of a request to add on the size of this download to the total |
| 70 | -- (void)incrementDownloadSizeBy:(int)bytes; | 70 | +- (void)incrementDownloadSizeBy:(unsigned long long)bytes; |
| 71 | 71 | ||
| 72 | // Called during a request when data is received to increment the progress indicator | 72 | // Called during a request when data is received to increment the progress indicator |
| 73 | -- (void)incrementDownloadProgressBy:(int)bytes; | 73 | +- (void)incrementDownloadProgressBy:(unsigned long long)bytes; |
| 74 | + | ||
| 75 | +// Called during a request when authorisation fails to cancel any progress so far | ||
| 76 | +- (void)decrementUploadProgressBy:(unsigned long long)bytes; | ||
| 74 | 77 | ||
| 75 | // All ASINetworkQueues are paused when created so that total size can be calculated before the queue starts | 78 | // All ASINetworkQueues are paused when created so that total size can be calculated before the queue starts |
| 76 | // This method will start the queue | 79 | // This method will start the queue |
| @@ -34,6 +34,7 @@ | @@ -34,6 +34,7 @@ | ||
| 34 | 34 | ||
| 35 | showAccurateProgress = NO; | 35 | showAccurateProgress = NO; |
| 36 | 36 | ||
| 37 | + [self setMaxConcurrentOperationCount:4]; | ||
| 37 | [self setSuspended:YES]; | 38 | [self setSuspended:YES]; |
| 38 | 39 | ||
| 39 | return self; | 40 | return self; |
| @@ -59,9 +60,6 @@ | @@ -59,9 +60,6 @@ | ||
| 59 | uploadProgressTotalBytes = 0; | 60 | uploadProgressTotalBytes = 0; |
| 60 | downloadProgressBytes = 0; | 61 | downloadProgressBytes = 0; |
| 61 | downloadProgressTotalBytes = 0; | 62 | downloadProgressTotalBytes = 0; |
| 62 | - [self setUploadProgressDelegate:nil]; | ||
| 63 | - [self setDownloadProgressDelegate:nil]; | ||
| 64 | - [self setDelegate:nil]; | ||
| 65 | [super cancelAllOperations]; | 63 | [super cancelAllOperations]; |
| 66 | } | 64 | } |
| 67 | 65 | ||
| @@ -103,6 +101,8 @@ | @@ -103,6 +101,8 @@ | ||
| 103 | if ([operation isKindOfClass:[ASIHTTPRequest class]]) { | 101 | if ([operation isKindOfClass:[ASIHTTPRequest class]]) { |
| 104 | 102 | ||
| 105 | ASIHTTPRequest *request = (ASIHTTPRequest *)operation; | 103 | ASIHTTPRequest *request = (ASIHTTPRequest *)operation; |
| 104 | + [request setRequestMethod:@"HEAD"]; | ||
| 105 | + [request setQueuePriority:10]; | ||
| 106 | [request setShowAccurateProgress:YES]; | 106 | [request setShowAccurateProgress:YES]; |
| 107 | if (uploadProgressDelegate) { | 107 | if (uploadProgressDelegate) { |
| 108 | [request setUploadProgressDelegate:self]; | 108 | [request setUploadProgressDelegate:self]; |
| @@ -133,12 +133,11 @@ | @@ -133,12 +133,11 @@ | ||
| 133 | //If this is a GET request and we want accurate progress, perform a HEAD request first to get the content-length | 133 | //If this is a GET request and we want accurate progress, perform a HEAD request first to get the content-length |
| 134 | if ([[request requestMethod] isEqualToString:@"GET"]) { | 134 | if ([[request requestMethod] isEqualToString:@"GET"]) { |
| 135 | ASIHTTPRequest *HEADRequest = [[[ASIHTTPRequest alloc] initWithURL:[request url]] autorelease]; | 135 | ASIHTTPRequest *HEADRequest = [[[ASIHTTPRequest alloc] initWithURL:[request url]] autorelease]; |
| 136 | - [HEADRequest setRequestMethod:@"HEAD"]; | ||
| 137 | - [HEADRequest setQueuePriority:10]; | ||
| 138 | [HEADRequest setMainRequest:request]; | 136 | [HEADRequest setMainRequest:request]; |
| 139 | [self addHEADOperation:HEADRequest]; | 137 | [self addHEADOperation:HEADRequest]; |
| 140 | 138 | ||
| 141 | - [request setUseCachedContentLength:YES]; | 139 | + //Tell the request not to reset the progress indicator when it gets a content-length, as we will get the length from the HEAD request |
| 140 | + [request setShouldResetProgressIndicators:NO]; | ||
| 142 | [request addDependency:HEADRequest]; | 141 | [request addDependency:HEADRequest]; |
| 143 | 142 | ||
| 144 | //If we want to track uploading for this request accurately, we need to add the size of the post content to the total | 143 | //If we want to track uploading for this request accurately, we need to add the size of the post content to the total |
| @@ -150,6 +149,9 @@ | @@ -150,6 +149,9 @@ | ||
| 150 | [request setShowAccurateProgress:showAccurateProgress]; | 149 | [request setShowAccurateProgress:showAccurateProgress]; |
| 151 | 150 | ||
| 152 | if (uploadProgressDelegate) { | 151 | if (uploadProgressDelegate) { |
| 152 | + | ||
| 153 | + //For uploads requests, we always work out the total upload size before the queue starts, so we tell the request not to reset the progress indicator when starting each request | ||
| 154 | + [request setShouldResetProgressIndicators:NO]; | ||
| 153 | [request setUploadProgressDelegate:self]; | 155 | [request setUploadProgressDelegate:self]; |
| 154 | } else { | 156 | } else { |
| 155 | [request setUploadProgressDelegate:NULL]; | 157 | [request setUploadProgressDelegate:NULL]; |
| @@ -173,7 +175,7 @@ | @@ -173,7 +175,7 @@ | ||
| 173 | if (requestDidFailSelector) { | 175 | if (requestDidFailSelector) { |
| 174 | [delegate performSelector:requestDidFailSelector withObject:request]; | 176 | [delegate performSelector:requestDidFailSelector withObject:request]; |
| 175 | } | 177 | } |
| 176 | - if (shouldCancelAllRequestsOnFailure) { | 178 | + if (shouldCancelAllRequestsOnFailure && requestsCount > 0) { |
| 177 | [self cancelAllOperations]; | 179 | [self cancelAllOperations]; |
| 178 | } | 180 | } |
| 179 | } | 181 | } |
| @@ -191,7 +193,7 @@ | @@ -191,7 +193,7 @@ | ||
| 191 | } | 193 | } |
| 192 | } | 194 | } |
| 193 | 195 | ||
| 194 | -- (void)incrementUploadSizeBy:(int)bytes | 196 | +- (void)incrementUploadSizeBy:(unsigned long long)bytes |
| 195 | { | 197 | { |
| 196 | if (!uploadProgressDelegate) { | 198 | if (!uploadProgressDelegate) { |
| 197 | return; | 199 | return; |
| @@ -200,7 +202,19 @@ | @@ -200,7 +202,19 @@ | ||
| 200 | [self incrementUploadProgressBy:0]; | 202 | [self incrementUploadProgressBy:0]; |
| 201 | } | 203 | } |
| 202 | 204 | ||
| 203 | -- (void)incrementUploadProgressBy:(int)bytes | 205 | +- (void)decrementUploadProgressBy:(unsigned long long)bytes |
| 206 | +{ | ||
| 207 | + if (!uploadProgressDelegate || uploadProgressTotalBytes == 0) { | ||
| 208 | + return; | ||
| 209 | + } | ||
| 210 | + uploadProgressBytes -= bytes; | ||
| 211 | + | ||
| 212 | + double progress = (uploadProgressBytes*1.0)/(uploadProgressTotalBytes*1.0); | ||
| 213 | + [ASIHTTPRequest setProgress:progress forProgressIndicator:uploadProgressDelegate]; | ||
| 214 | +} | ||
| 215 | + | ||
| 216 | + | ||
| 217 | +- (void)incrementUploadProgressBy:(unsigned long long)bytes | ||
| 204 | { | 218 | { |
| 205 | if (!uploadProgressDelegate || uploadProgressTotalBytes == 0) { | 219 | if (!uploadProgressDelegate || uploadProgressTotalBytes == 0) { |
| 206 | return; | 220 | return; |
| @@ -209,24 +223,26 @@ | @@ -209,24 +223,26 @@ | ||
| 209 | 223 | ||
| 210 | double progress = (uploadProgressBytes*1.0)/(uploadProgressTotalBytes*1.0); | 224 | double progress = (uploadProgressBytes*1.0)/(uploadProgressTotalBytes*1.0); |
| 211 | [ASIHTTPRequest setProgress:progress forProgressIndicator:uploadProgressDelegate]; | 225 | [ASIHTTPRequest setProgress:progress forProgressIndicator:uploadProgressDelegate]; |
| 226 | + | ||
| 212 | } | 227 | } |
| 213 | 228 | ||
| 214 | -- (void)incrementDownloadSizeBy:(int)bytes | 229 | +- (void)incrementDownloadSizeBy:(unsigned long long)bytes |
| 215 | { | 230 | { |
| 216 | if (!downloadProgressDelegate) { | 231 | if (!downloadProgressDelegate) { |
| 217 | return; | 232 | return; |
| 218 | } | 233 | } |
| 219 | downloadProgressTotalBytes += bytes; | 234 | downloadProgressTotalBytes += bytes; |
| 220 | [self incrementDownloadProgressBy:0]; | 235 | [self incrementDownloadProgressBy:0]; |
| 236 | + NSLog(@"download size is now: %qu",downloadProgressTotalBytes); | ||
| 221 | } | 237 | } |
| 222 | 238 | ||
| 223 | -- (void)incrementDownloadProgressBy:(int)bytes | 239 | +- (void)incrementDownloadProgressBy:(unsigned long long)bytes |
| 224 | { | 240 | { |
| 225 | if (!downloadProgressDelegate || downloadProgressTotalBytes == 0) { | 241 | if (!downloadProgressDelegate || downloadProgressTotalBytes == 0) { |
| 226 | return; | 242 | return; |
| 227 | } | 243 | } |
| 228 | downloadProgressBytes += bytes; | 244 | downloadProgressBytes += bytes; |
| 229 | - //NSLog(@"%hu/%hu",downloadProgressBytes,downloadProgressTotalBytes); | 245 | + //NSLog(@"%qu/%qu",downloadProgressBytes,downloadProgressTotalBytes); |
| 230 | double progress = (downloadProgressBytes*1.0)/(downloadProgressTotalBytes*1.0); | 246 | double progress = (downloadProgressBytes*1.0)/(downloadProgressTotalBytes*1.0); |
| 231 | [ASIHTTPRequest setProgress:progress forProgressIndicator:downloadProgressDelegate]; | 247 | [ASIHTTPRequest setProgress:progress forProgressIndicator:downloadProgressDelegate]; |
| 232 | } | 248 | } |
| @@ -201,8 +201,6 @@ | @@ -201,8 +201,6 @@ | ||
| 201 | 201 | ||
| 202 | - (void)requestFailedCancellingOthers:(ASIHTTPRequest *)request | 202 | - (void)requestFailedCancellingOthers:(ASIHTTPRequest *)request |
| 203 | { | 203 | { |
| 204 | - BOOL success = (request == requestThatShouldFail); | ||
| 205 | - STAssertTrue(success,@"Wrong request failed"); | ||
| 206 | complete = YES; | 204 | complete = YES; |
| 207 | } | 205 | } |
| 208 | 206 |
-
Please register or login to post a comment