Showing
7 changed files
with
42 additions
and
1 deletions
| @@ -122,7 +122,10 @@ | @@ -122,7 +122,10 @@ | ||
| 122 | //Called on the delegate when the request fails | 122 | //Called on the delegate when the request fails |
| 123 | SEL didFailSelector; | 123 | SEL didFailSelector; |
| 124 | 124 | ||
| 125 | + //Used for recording when something last happened during the request, we will compare this value with the current date to time out requests when appropriate | ||
| 126 | + NSDate *lastActivityTime; | ||
| 125 | 127 | ||
| 128 | + NSTimeInterval timeOutSeconds; | ||
| 126 | } | 129 | } |
| 127 | 130 | ||
| 128 | #pragma mark init / dealloc | 131 | #pragma mark init / dealloc |
| @@ -254,5 +257,6 @@ | @@ -254,5 +257,6 @@ | ||
| 254 | @property (retain) NSDictionary *requestCredentials; | 257 | @property (retain) NSDictionary *requestCredentials; |
| 255 | @property (assign) int responseStatusCode; | 258 | @property (assign) int responseStatusCode; |
| 256 | @property (retain) NSMutableData *receivedData; | 259 | @property (retain) NSMutableData *receivedData; |
| 257 | - | 260 | +@property (retain) NSDate *lastActivityTime; |
| 261 | +@property (assign) NSTimeInterval timeOutSeconds; | ||
| 258 | @end | 262 | @end |
| @@ -51,6 +51,7 @@ static void ReadStreamClientCallBack(CFReadStreamRef readStream, CFStreamEventTy | @@ -51,6 +51,7 @@ static void ReadStreamClientCallBack(CFReadStreamRef readStream, CFStreamEventTy | ||
| 51 | //credentials = NULL; | 51 | //credentials = NULL; |
| 52 | request = NULL; | 52 | request = NULL; |
| 53 | responseHeaders = nil; | 53 | responseHeaders = nil; |
| 54 | + [self setTimeOutSeconds:30]; | ||
| 54 | [self setUseKeychainPersistance:NO]; | 55 | [self setUseKeychainPersistance:NO]; |
| 55 | [self setUseSessionPersistance:YES]; | 56 | [self setUseSessionPersistance:YES]; |
| 56 | [self setUseCookiePersistance:YES]; | 57 | [self setUseCookiePersistance:YES]; |
| @@ -83,6 +84,7 @@ static void ReadStreamClientCallBack(CFReadStreamRef readStream, CFStreamEventTy | @@ -83,6 +84,7 @@ static void ReadStreamClientCallBack(CFReadStreamRef readStream, CFStreamEventTy | ||
| 83 | [authenticationRealm release]; | 84 | [authenticationRealm release]; |
| 84 | [url release]; | 85 | [url release]; |
| 85 | [authenticationLock release]; | 86 | [authenticationLock release]; |
| 87 | + [lastActivityTime release]; | ||
| 86 | [super dealloc]; | 88 | [super dealloc]; |
| 87 | } | 89 | } |
| 88 | 90 | ||
| @@ -304,11 +306,23 @@ static void ReadStreamClientCallBack(CFReadStreamRef readStream, CFStreamEventTy | @@ -304,11 +306,23 @@ static void ReadStreamClientCallBack(CFReadStreamRef readStream, CFStreamEventTy | ||
| 304 | [self performSelectorOnMainThread:@selector(resetUploadProgress:) withObject:[NSNumber numberWithDouble:postLength] waitUntilDone:YES]; | 306 | [self performSelectorOnMainThread:@selector(resetUploadProgress:) withObject:[NSNumber numberWithDouble:postLength] waitUntilDone:YES]; |
| 305 | } | 307 | } |
| 306 | 308 | ||
| 309 | + //Record when the request started, so we can timeout if nothing happens | ||
| 310 | + [self setLastActivityTime:[[NSDate new] autorelease]]; | ||
| 307 | 311 | ||
| 308 | // Wait for the request to finish | 312 | // Wait for the request to finish |
| 309 | NSDate* endDate = [NSDate distantFuture]; | 313 | NSDate* endDate = [NSDate distantFuture]; |
| 310 | while (!complete) { | 314 | while (!complete) { |
| 311 | 315 | ||
| 316 | + //See if we need to timeout | ||
| 317 | + if (lastActivityTime && timeOutSeconds > 0) { | ||
| 318 | + if ([[[NSDate new] autorelease] timeIntervalSinceDate:lastActivityTime] > timeOutSeconds) { | ||
| 319 | + [self failWithProblem:@"Request timed out"]; | ||
| 320 | + [self cancelLoad]; | ||
| 321 | + complete = YES; | ||
| 322 | + break; | ||
| 323 | + } | ||
| 324 | + } | ||
| 325 | + | ||
| 312 | // See if our NSOperationQueue told us to cancel | 326 | // See if our NSOperationQueue told us to cancel |
| 313 | if ([self isCancelled]) { | 327 | if ([self isCancelled]) { |
| 314 | [self failWithProblem:@"The request was cancelled"]; | 328 | [self failWithProblem:@"The request was cancelled"]; |
| @@ -366,6 +380,8 @@ static void ReadStreamClientCallBack(CFReadStreamRef readStream, CFStreamEventTy | @@ -366,6 +380,8 @@ static void ReadStreamClientCallBack(CFReadStreamRef readStream, CFStreamEventTy | ||
| 366 | 380 | ||
| 367 | - (void)updateUploadProgress | 381 | - (void)updateUploadProgress |
| 368 | { | 382 | { |
| 383 | + [self setLastActivityTime:[[NSDate new] autorelease]]; | ||
| 384 | + | ||
| 369 | double byteCount = [[(NSNumber *)CFReadStreamCopyProperty (readStream, kCFStreamPropertyHTTPRequestBytesWrittenCount) autorelease] doubleValue]; | 385 | double byteCount = [[(NSNumber *)CFReadStreamCopyProperty (readStream, kCFStreamPropertyHTTPRequestBytesWrittenCount) autorelease] doubleValue]; |
| 370 | if (uploadProgressDelegate) { | 386 | if (uploadProgressDelegate) { |
| 371 | [uploadProgressDelegate incrementBy:byteCount-lastBytesSent]; | 387 | [uploadProgressDelegate incrementBy:byteCount-lastBytesSent]; |
| @@ -385,6 +401,8 @@ static void ReadStreamClientCallBack(CFReadStreamRef readStream, CFStreamEventTy | @@ -385,6 +401,8 @@ static void ReadStreamClientCallBack(CFReadStreamRef readStream, CFStreamEventTy | ||
| 385 | 401 | ||
| 386 | - (void)updateDownloadProgress | 402 | - (void)updateDownloadProgress |
| 387 | { | 403 | { |
| 404 | + [self setLastActivityTime:[[NSDate new] autorelease]]; | ||
| 405 | + | ||
| 388 | //We won't update downlaod progress until we've examined the headers, since we might need to authenticate | 406 | //We won't update downlaod progress until we've examined the headers, since we might need to authenticate |
| 389 | if (downloadProgressDelegate && responseHeaders) { | 407 | if (downloadProgressDelegate && responseHeaders) { |
| 390 | [downloadProgressDelegate incrementBy:totalBytesRead-lastBytesRead]; | 408 | [downloadProgressDelegate incrementBy:totalBytesRead-lastBytesRead]; |
| @@ -586,6 +604,7 @@ static void ReadStreamClientCallBack(CFReadStreamRef readStream, CFStreamEventTy | @@ -586,6 +604,7 @@ static void ReadStreamClientCallBack(CFReadStreamRef readStream, CFStreamEventTy | ||
| 586 | // check for bad credentials, so we can give the delegate a chance to replace them | 604 | // check for bad credentials, so we can give the delegate a chance to replace them |
| 587 | if (err.domain == kCFStreamErrorDomainHTTP && (err.error == kCFStreamErrorHTTPAuthenticationBadUserName || err.error == kCFStreamErrorHTTPAuthenticationBadPassword)) { | 605 | if (err.domain == kCFStreamErrorDomainHTTP && (err.error == kCFStreamErrorHTTPAuthenticationBadUserName || err.error == kCFStreamErrorHTTPAuthenticationBadPassword)) { |
| 588 | ignoreError = YES; | 606 | ignoreError = YES; |
| 607 | + [self setLastActivityTime:nil]; | ||
| 589 | if ([delegate respondsToSelector:@selector(authorizationNeededForRequest:)]) { | 608 | if ([delegate respondsToSelector:@selector(authorizationNeededForRequest:)]) { |
| 590 | [delegate performSelectorOnMainThread:@selector(authorizationNeededForRequest:) withObject:self waitUntilDone:YES]; | 609 | [delegate performSelectorOnMainThread:@selector(authorizationNeededForRequest:) withObject:self waitUntilDone:YES]; |
| 591 | [authenticationLock lockWhenCondition:2]; | 610 | [authenticationLock lockWhenCondition:2]; |
| @@ -863,4 +882,6 @@ static void ReadStreamClientCallBack(CFReadStreamRef readStream, CFStreamEventTy | @@ -863,4 +882,6 @@ static void ReadStreamClientCallBack(CFReadStreamRef readStream, CFStreamEventTy | ||
| 863 | @synthesize requestCredentials; | 882 | @synthesize requestCredentials; |
| 864 | @synthesize responseStatusCode; | 883 | @synthesize responseStatusCode; |
| 865 | @synthesize receivedData; | 884 | @synthesize receivedData; |
| 885 | +@synthesize lastActivityTime; | ||
| 886 | +@synthesize timeOutSeconds; | ||
| 866 | @end | 887 | @end |
| @@ -58,6 +58,20 @@ More tests needed for: | @@ -58,6 +58,20 @@ More tests needed for: | ||
| 58 | STAssertNotNil(error,@"Failed to generate an error for a bad host - this test may fail when your DNS server redirects you to another page when it can't find a domain name (eg OpenDNS)"); | 58 | STAssertNotNil(error,@"Failed to generate an error for a bad host - this test may fail when your DNS server redirects you to another page when it can't find a domain name (eg OpenDNS)"); |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | +- (void)testTimeOut | ||
| 62 | +{ | ||
| 63 | + //Grab data | ||
| 64 | + NSURL *url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com"] autorelease]; | ||
| 65 | + ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease]; | ||
| 66 | + [request setTimeOutSeconds:0.0001]; //It's pretty unlikely we will be able to grab the data this quickly, so the request should timeout | ||
| 67 | + [request start]; | ||
| 68 | + NSError *error = [request error]; | ||
| 69 | + STAssertNotNil(error,@"Request didn't timeout"); | ||
| 70 | + BOOL success = [[[error userInfo] valueForKey:@"Description"] isEqualToString:@"Request timed out"]; | ||
| 71 | + STAssertTrue(success,@"Timeout didn't generate the correct error"); | ||
| 72 | + | ||
| 73 | +} | ||
| 74 | + | ||
| 61 | - (void)testOperationQueue | 75 | - (void)testOperationQueue |
| 62 | { | 76 | { |
| 63 | NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease]; | 77 | NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease]; |
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
-
Please register or login to post a comment