This app provides monitoring and information features for the common freifunk user and the technical stuff of a freifunk community.
Code base is taken from a TUM Practical Course project and added here to see if Freifunk Altdorf can use it.
https://www.freifunk-altdorf.de
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
200 lines
4.7 KiB
200 lines
4.7 KiB
/** |
|
* Copyright (c) 2015-present, Facebook, Inc. |
|
* |
|
* This source code is licensed under the MIT license found in the |
|
* LICENSE file in the root directory of this source tree. |
|
*/ |
|
|
|
#import <React/RCTLog.h> |
|
#import <React/RCTNetworkTask.h> |
|
#import <React/RCTUtils.h> |
|
|
|
@implementation RCTNetworkTask |
|
{ |
|
NSMutableData *_data; |
|
id<RCTURLRequestHandler> _handler; |
|
dispatch_queue_t _callbackQueue; |
|
|
|
RCTNetworkTask *_selfReference; |
|
} |
|
|
|
- (instancetype)initWithRequest:(NSURLRequest *)request |
|
handler:(id<RCTURLRequestHandler>)handler |
|
callbackQueue:(dispatch_queue_t)callbackQueue |
|
{ |
|
RCTAssertParam(request); |
|
RCTAssertParam(handler); |
|
RCTAssertParam(callbackQueue); |
|
|
|
static NSUInteger requestID = 0; |
|
|
|
if ((self = [super init])) { |
|
_requestID = @(requestID++); |
|
_request = request; |
|
_handler = handler; |
|
_callbackQueue = callbackQueue; |
|
_status = RCTNetworkTaskPending; |
|
|
|
dispatch_queue_set_specific(callbackQueue, (__bridge void *)self, (__bridge void *)self, NULL); |
|
} |
|
return self; |
|
} |
|
|
|
RCT_NOT_IMPLEMENTED(- (instancetype)init) |
|
|
|
- (void)invalidate |
|
{ |
|
_selfReference = nil; |
|
_completionBlock = nil; |
|
_downloadProgressBlock = nil; |
|
_incrementalDataBlock = nil; |
|
_responseBlock = nil; |
|
_uploadProgressBlock = nil; |
|
_requestToken = nil; |
|
} |
|
|
|
- (void)dispatchCallback:(dispatch_block_t)callback |
|
{ |
|
if (dispatch_get_specific((__bridge void *)self) == (__bridge void *)self) { |
|
callback(); |
|
} else { |
|
dispatch_async(_callbackQueue, callback); |
|
} |
|
} |
|
|
|
- (void)start |
|
{ |
|
if (_status != RCTNetworkTaskPending) { |
|
RCTLogError(@"RCTNetworkTask was already started or completed"); |
|
return; |
|
} |
|
|
|
if (_requestToken == nil) { |
|
id token = [_handler sendRequest:_request withDelegate:self]; |
|
if ([self validateRequestToken:token]) { |
|
_selfReference = self; |
|
_status = RCTNetworkTaskInProgress; |
|
} |
|
} |
|
} |
|
|
|
- (void)cancel |
|
{ |
|
if (_status == RCTNetworkTaskFinished) { |
|
return; |
|
} |
|
|
|
_status = RCTNetworkTaskFinished; |
|
id token = _requestToken; |
|
if (token && [_handler respondsToSelector:@selector(cancelRequest:)]) { |
|
[_handler cancelRequest:token]; |
|
} |
|
[self invalidate]; |
|
} |
|
|
|
- (BOOL)validateRequestToken:(id)requestToken |
|
{ |
|
BOOL valid = YES; |
|
if (_requestToken == nil) { |
|
if (requestToken == nil) { |
|
if (RCT_DEBUG) { |
|
RCTLogError(@"Missing request token for request: %@", _request); |
|
} |
|
valid = NO; |
|
} |
|
_requestToken = requestToken; |
|
} else if (![requestToken isEqual:_requestToken]) { |
|
if (RCT_DEBUG) { |
|
RCTLogError(@"Unrecognized request token: %@ expected: %@", requestToken, _requestToken); |
|
} |
|
valid = NO; |
|
} |
|
|
|
if (!valid) { |
|
_status = RCTNetworkTaskFinished; |
|
if (_completionBlock) { |
|
RCTURLRequestCompletionBlock completionBlock = _completionBlock; |
|
[self dispatchCallback:^{ |
|
completionBlock(self->_response, nil, RCTErrorWithMessage(@"Invalid request token.")); |
|
}]; |
|
} |
|
[self invalidate]; |
|
} |
|
return valid; |
|
} |
|
|
|
- (void)URLRequest:(id)requestToken didSendDataWithProgress:(int64_t)bytesSent |
|
{ |
|
if (![self validateRequestToken:requestToken]) { |
|
return; |
|
} |
|
|
|
if (_uploadProgressBlock) { |
|
RCTURLRequestProgressBlock uploadProgressBlock = _uploadProgressBlock; |
|
int64_t length = _request.HTTPBody.length; |
|
[self dispatchCallback:^{ |
|
uploadProgressBlock(bytesSent, length); |
|
}]; |
|
} |
|
} |
|
|
|
- (void)URLRequest:(id)requestToken didReceiveResponse:(NSURLResponse *)response |
|
{ |
|
if (![self validateRequestToken:requestToken]) { |
|
return; |
|
} |
|
|
|
_response = response; |
|
if (_responseBlock) { |
|
RCTURLRequestResponseBlock responseBlock = _responseBlock; |
|
[self dispatchCallback:^{ |
|
responseBlock(response); |
|
}]; |
|
} |
|
} |
|
|
|
- (void)URLRequest:(id)requestToken didReceiveData:(NSData *)data |
|
{ |
|
if (![self validateRequestToken:requestToken]) { |
|
return; |
|
} |
|
|
|
if (!_data) { |
|
_data = [NSMutableData new]; |
|
} |
|
[_data appendData:data]; |
|
|
|
int64_t length = _data.length; |
|
int64_t total = _response.expectedContentLength; |
|
|
|
if (_incrementalDataBlock) { |
|
RCTURLRequestIncrementalDataBlock incrementalDataBlock = _incrementalDataBlock; |
|
[self dispatchCallback:^{ |
|
incrementalDataBlock(data, length, total); |
|
}]; |
|
} |
|
if (_downloadProgressBlock && total > 0) { |
|
RCTURLRequestProgressBlock downloadProgressBlock = _downloadProgressBlock; |
|
[self dispatchCallback:^{ |
|
downloadProgressBlock(length, total); |
|
}]; |
|
} |
|
} |
|
|
|
- (void)URLRequest:(id)requestToken didCompleteWithError:(NSError *)error |
|
{ |
|
if (![self validateRequestToken:requestToken]) { |
|
return; |
|
} |
|
|
|
_status = RCTNetworkTaskFinished; |
|
if (_completionBlock) { |
|
RCTURLRequestCompletionBlock completionBlock = _completionBlock; |
|
[self dispatchCallback:^{ |
|
completionBlock(self->_response, self->_data, error); |
|
}]; |
|
} |
|
[self invalidate]; |
|
} |
|
|
|
@end
|
|
|