diff options
author | Konstantin Käfer <mail@kkaefer.com> | 2014-09-22 13:06:40 +0200 |
---|---|---|
committer | Konstantin Käfer <mail@kkaefer.com> | 2014-09-24 16:16:29 +0200 |
commit | 3f38c7650e6d76fe5e6fd6d8f2f3174af0c2e176 (patch) | |
tree | c97cc8e65062c2d4faefbe1f5d0c337f1e1874b4 /src/storage/http_request_baton_darwin.mm | |
parent | a142fd5e3a9da2a24ee3effc87519f9e1466655c (diff) | |
download | qtlocation-mapboxgl-3f38c7650e6d76fe5e6fd6d8f2f3174af0c2e176.tar.gz |
add retry timers
Diffstat (limited to 'src/storage/http_request_baton_darwin.mm')
-rw-r--r-- | src/storage/http_request_baton_darwin.mm | 75 |
1 files changed, 61 insertions, 14 deletions
diff --git a/src/storage/http_request_baton_darwin.mm b/src/storage/http_request_baton_darwin.mm index b1e47e3508..eaf75ad4d1 100644 --- a/src/storage/http_request_baton_darwin.mm +++ b/src/storage/http_request_baton_darwin.mm @@ -1,8 +1,11 @@ #include <mbgl/storage/http_request_baton.hpp> +#include <mbgl/util/std.hpp> #include <mbgl/util/parsedate.h> #include <uv.h> +#include <mbgl/util/uv.hpp> + #import <Foundation/Foundation.h> #include <ctime> #include <xlocale.h> @@ -14,6 +17,7 @@ NSURLSession *session = nullptr; void HTTPRequestBaton::start() { // Starts the request. + assert(!ptr); // Create a C locale static locale_t locale = newlocale(LC_ALL_MASK, nullptr, nullptr); @@ -28,7 +32,6 @@ void HTTPRequestBaton::start() { // TODO: add a delegate to the session that prohibits caching, since we handle this ourselves. }); - NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@(path.c_str())]]; if (response && response->modified) { struct tm *timeinfo; @@ -41,30 +44,63 @@ void HTTPRequestBaton::start() { NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *res, NSError *error) { - if (error) { - if ([error code] != NSURLErrorCancelled) { + if ([error code] == NSURLErrorCancelled) { + // The response code remains at 0 to indicate cancelation. + // In addition, we don't need any response object. + response.reset(); + type = HTTPResponseType::Canceled; + } else { // TODO: Use different codes for host not found, timeout, invalid URL etc. // These can be categorized in temporary and permanent errors. - response = std::unique_ptr<Response>(new Response); - response->code = -1; + response = std::make_unique<Response>(); + response->code = [(NSHTTPURLResponse *)res statusCode]; response->message = [[error localizedDescription] UTF8String]; - } else { - // This request was canceled. - // The response code remains at 0 to indicate cancelation. + + switch ([error code]) { + case NSURLErrorBadServerResponse: // 5xx errors + type = HTTPResponseType::TemporaryError; + break; + + case NSURLErrorTimedOut: + case NSURLErrorUserCancelledAuthentication: + type = HTTPResponseType::SingularError; // retry immediately + break; + + case NSURLErrorNetworkConnectionLost: + case NSURLErrorCannotFindHost: + case NSURLErrorCannotConnectToHost: + case NSURLErrorDNSLookupFailed: + case NSURLErrorNotConnectedToInternet: + case NSURLErrorInternationalRoamingOff: + case NSURLErrorCallIsActive: + case NSURLErrorDataNotAllowed: + type = HTTPResponseType::ConnectionError; + break; + + default: + type = HTTPResponseType::PermanentError; + } } } else if ([res isKindOfClass:[NSHTTPURLResponse class]]) { const long code = [(NSHTTPURLResponse *)res statusCode]; if (code == 304) { // Assume a Response object already exists. assert(response); - not_modified = true; } else { - response = std::unique_ptr<Response>(new Response); + response = std::make_unique<Response>(); response->code = code; response->data = {(const char *)[data bytes], [data length]}; } + if (code == 304) { + type = HTTPResponseType::NotModified; + } else if (code == 200) { + type = HTTPResponseType::Successful; + } else { + assert(!"code must be either 200 or 304"); + } + NSDictionary *headers = [(NSHTTPURLResponse *)res allHeaderFields]; NSString *cache_control = [headers objectForKey:@"Cache-Control"]; if (cache_control) { @@ -77,26 +113,37 @@ void HTTPRequestBaton::start() { } } else { // This should never happen. - response = std::unique_ptr<Response>(new Response); + type = HTTPResponseType::PermanentError; + response = std::make_unique<Response>(); response->code = -1; response->message = "response class is not NSHTTPURLResponse"; - // TODO: If we get a failure, we should not overwrite a potentially existing response. } uv_async_send(async); }]; + [task resume]; + ptr = const_cast<void *>(CFBridgingRetain(task)); +} - [task resume]; +void HTTPRequestBaton::cleanup() { + if (ptr) { + CFBridgingRelease(ptr); + ptr = nullptr; + } } void HTTPRequestBaton::cancel() { // After this function returns, the HTTPRequestBaton object may cease to exist at any time. // try to stop the request if (ptr) { - [(NSURLSessionDataTask *)CFBridgingRelease(ptr) cancel]; + NSURLSessionDataTask *task = CFBridgingRelease(ptr); ptr = nullptr; + [task cancel]; + } else { + // Currently, there is no request in progress. We can delete the async right away. + uv_async_send(async); } } |