summaryrefslogtreecommitdiff
path: root/src/storage/http_request_baton_darwin.mm
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2014-09-22 13:06:40 +0200
committerKonstantin Käfer <mail@kkaefer.com>2014-09-24 16:16:29 +0200
commit3f38c7650e6d76fe5e6fd6d8f2f3174af0c2e176 (patch)
treec97cc8e65062c2d4faefbe1f5d0c337f1e1874b4 /src/storage/http_request_baton_darwin.mm
parenta142fd5e3a9da2a24ee3effc87519f9e1466655c (diff)
downloadqtlocation-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.mm75
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);
}
}