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