diff options
| author | NicoleYarroch <nicole@livio.io> | 2017-04-07 16:05:47 -0400 |
|---|---|---|
| committer | NicoleYarroch <nicole@livio.io> | 2017-04-07 16:05:47 -0400 |
| commit | 2f11487dd9edf2ba2704c01a26316dd5239833d2 (patch) | |
| tree | 47ed679b51fc5fc3622755d88b9cd1f893f2fb1a /SmartDeviceLink/SDLUploadFileOperation.m | |
| parent | 7574184d7acc40a56679004eff98cf6d4a48eb33 (diff) | |
| download | sdl_ios-2f11487dd9edf2ba2704c01a26316dd5239833d2.tar.gz | |
Cleaned up comments in the SDLUploadFileOperation class
Signed-off-by: NicoleYarroch <nicole@livio.io>
Diffstat (limited to 'SmartDeviceLink/SDLUploadFileOperation.m')
| -rw-r--r-- | SmartDeviceLink/SDLUploadFileOperation.m | 119 |
1 files changed, 59 insertions, 60 deletions
diff --git a/SmartDeviceLink/SDLUploadFileOperation.m b/SmartDeviceLink/SDLUploadFileOperation.m index f16288a3b..06a5370d0 100644 --- a/SmartDeviceLink/SDLUploadFileOperation.m +++ b/SmartDeviceLink/SDLUploadFileOperation.m @@ -51,39 +51,40 @@ NS_ASSUME_NONNULL_BEGIN - (void)start { [super start]; - [self sendPutFiles:self.fileWrapper.file mtuSize:[SDLGlobals sharedGlobals].maxMTUSize withCompletion:self.fileWrapper.completionHandler]; } -- (void)sendPutFiles:(SDLFile *)file mtuSize:(NSUInteger)mtuSize withCompletion:(SDLFileManagerUploadCompletionHandler)completion { +/** + Sends data asychronously to the SDL Core by breaking the data into smaller pieces, each of which is sent via a putfile. When all sent putfiles are acknowledged by the SDL Core, a closure returns the whether or not the data was uploaded successfully to the SDL Core. - // iStream is NSInputStream instance variable - self.inputStream = file.inputStream; - [self.inputStream setDelegate:self]; - [self.inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] - forMode:NSDefaultRunLoopMode]; - [self.inputStream open]; + @param file The file containing the data to be sent to the SDL Core + @param mtuSize The maximum packet size allowed + @param completion Closure returning whether or not the upload was a success + */ +- (void)sendPutFiles:(SDLFile *)file mtuSize:(NSUInteger)mtuSize withCompletion:(SDLFileManagerUploadCompletionHandler)completion { + // The input stream is used to read data from both files and application memory + [self openInputStreamWithFile:file]; - // Wait for all data chunks be sent before executing the code in dispatch_group_notify dispatch_group_t putFileGroup = dispatch_group_create(); dispatch_group_enter(putFileGroup); + __weak typeof(self) weakself = self; __block BOOL stop = NO; __block NSError *streamError = nil; __block NSUInteger bytesAvailable = 0; __block NSInteger highestCorrelationIDReceived = -1; + + // Waits for all packets be sent before returning whether or not the upload was a success dispatch_group_notify(putFileGroup, dispatch_get_main_queue(), ^{ - // Was the data sent to the SDL Core successfully? if (streamError != nil || stop) { completion(NO, bytesAvailable, streamError); } else { completion(YES, bytesAvailable, nil); } - [weakself finishOperation]; }); - // Break the data into small chunks, each of which will be sent in a separate putfile + // Break the data into small pieces, each of which will be sent in a separate putfile unsigned long long fileSize = [file fileSize]; NSUInteger currentOffset = 0; unsigned long long numberOfFilesToSend = (((fileSize - 1) / mtuSize) + 1); @@ -97,16 +98,12 @@ NS_ASSUME_NONNULL_BEGIN putFile.length = @(putFileLength); // Get a chunk of data from the input stream - NSError *error = nil; - NSUInteger dataSize = [self getDataLengthForOffset:currentOffset fileSize:fileSize mtuSize:mtuSize]; - NSData *dataChunk = [self getDataChunkWithSize:dataSize inputStream:self.inputStream error:&error]; + NSUInteger dataSize = [self getDataSizeForOffset:currentOffset fileSize:fileSize mtuSize:mtuSize]; + NSData *dataChunk = [self getDataChunkWithSize:dataSize inputStream:self.inputStream]; if (dataChunk == nil) { - // TODO: - ????? Add error message here! - // return completion(NO, bytesAvailable, streamError); - [self cancel]; - streamError = error; + stop = YES; dispatch_group_leave(putFileGroup); - BLOCK_RETURN; + break; } putFile.bulkData = dataChunk; currentOffset += dataSize; @@ -115,18 +112,18 @@ NS_ASSUME_NONNULL_BEGIN __weak typeof(self) weakself = self; [self.connectionManager sendManagerRequest:putFile withResponseHandler:^(__kindof SDLRPCRequest *_Nullable request, __kindof SDLRPCResponse *_Nullable response, NSError *_Nullable error) { typeof(weakself) strongself = weakself; - // If we've already encountered an error, then just abort - // TODO: Is this the right way to handle this case? Should we just abort everything in the future? Should we be deleting what we sent? Should we have an automatic retry strategy based on what the error was? + + // Check if the upload process has been cancelled by another putfile. If it has, stop the upload process and return a completion handler with an unsuccessfull result. if (strongself.isCancelled) { + // TODO: Is this the right way to handle this case? Should we just abort everything in the future? Should we be deleting what we sent? Should we have an automatic retry strategy based on what the error was? stop = YES; } - if (stop) { dispatch_group_leave(putFileGroup); BLOCK_RETURN; } - // If we encounted an error, abort in the future and call the completion handler + // If the SDL Core returned an error, cancel the upload the process in the future if (error != nil || response == nil || ![response.success boolValue]) { stop = YES; streamError = error; @@ -134,10 +131,10 @@ NS_ASSUME_NONNULL_BEGIN BLOCK_RETURN; } - // If we haven't encounted an error + // If no errors, wait for all putfiles to return before returning a completion handler with a success result SDLPutFileResponse *putFileResponse = (SDLPutFileResponse *)response; - // We need to do this to make sure our bytesAvailable is accurate + // The number of bytes available is sent with the last response if ([request.correlationID integerValue] > highestCorrelationIDReceived) { highestCorrelationIDReceived = [request.correlationID integerValue]; bytesAvailable = [putFileResponse.spaceAvailable unsignedIntegerValue]; @@ -149,54 +146,71 @@ NS_ASSUME_NONNULL_BEGIN dispatch_group_leave(putFileGroup); } -- (NSInputStream *)openInputStreamWithFile:(SDLFile *)file { - NSInputStream *inputStream = file.inputStream; - [inputStream setDelegate:self]; - [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; - [inputStream open]; - return inputStream; +- (void)openInputStreamWithFile:(SDLFile *)file { + self.inputStream = file.inputStream; + [self.inputStream setDelegate:self]; + [self.inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] + forMode:NSDefaultRunLoopMode]; + [self.inputStream open]; } +/** + Returns the position in the file where to start reading data. + + @param currentOffset The current position in the file + @param fileSize The size of the file + @param mtuSize The maximum packet size allowed + @return The new position in the file where to start reading data + */ - (NSUInteger)getPutFileLengthForOffset:(NSUInteger)currentOffset fileSize:(unsigned long long)fileSize mtuSize:(NSUInteger)mtuSize { NSInteger putFileLength = 0; if (currentOffset == 0) { - // If the offset is 0, the putfile expects to have the full file size. + // The first putfile sends the full file size putFileLength = (NSInteger)fileSize; } else if ((fileSize - currentOffset) < mtuSize) { - // The file length remaining is smaller than the max data chunk sized allowed. The putfile expects the length parameter to match the size of the last data chunk being sent. + // The last putfile sends the size of the remaining data putFileLength = (NSInteger)(fileSize - currentOffset); } else { - // When the file length remaining is greater than the max data chunk sized allowed, and the offset is not zero, the putfile expects the length parameter to match the size of the data chunk being sent. + // All other putfiles send the maximum allowed packet size putFileLength = mtuSize; } return putFileLength; } -- (NSUInteger)getDataLengthForOffset:(NSUInteger)currentOffset fileSize:(unsigned long long)fileSize mtuSize:(NSUInteger)mtuSize { +/** + Gets the size of the data to be sent in a packet. Packet size can not be greater than the max MTU allowed by the SDL Core. + + @param currentOffset The position in the file where to start reading data + @param fileSize The size of the file + @param mtuSize The maximum packet size allowed + @return The size of the data to be sent in the packet. + */ +- (NSUInteger)getDataSizeForOffset:(NSUInteger)currentOffset fileSize:(unsigned long long)fileSize mtuSize:(NSUInteger)mtuSize { NSInteger dataSize = 0; NSUInteger fileSizeRemaining = (NSUInteger)(fileSize - currentOffset); if (fileSizeRemaining < mtuSize) { - // The file length remaining is smaller than the max data chunk sized allowed. The putfile expects the length parameter to match the size of the last data chunk being sent. dataSize = fileSizeRemaining; } else { - // When the file length remaining is greater than the max data chunk sized allowed, and the offset is not zero, the putfile expects the length parameter to match the size of the data chunk being sent. dataSize = mtuSize; } return dataSize; } -- (nullable NSData *)getDataChunkWithSize:(NSInteger)size inputStream:(NSInputStream *)inputStream error:(NSError **)error { +/** + Reads a chunk of data from a socket. + + @param size The amount of data to read from the input stream + @param inputStream The socket from which to read the data + @return The data read from the socket + */ +- (nullable NSData *)getDataChunkWithSize:(NSInteger)size inputStream:(NSInputStream *)inputStream { uint8_t buffer[size]; NSInteger bytesRead = [inputStream read:buffer maxLength:size]; if (bytesRead) { - // Return the bytes read into the buffer NSData *dataChunk = [[NSData alloc] initWithBytes:(const void*)buffer length:size]; return dataChunk; } else { - NSLog(@"nothing was read from the input stream"); - if (error) { - // TODO: return error - } + // TODO: return a custom error? return nil; } } @@ -215,25 +229,10 @@ NS_ASSUME_NONNULL_BEGIN - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { switch (eventCode) { - case NSStreamEventErrorOccurred: - NSLog(@"Input stream error occured"); case NSStreamEventEndEncountered: - NSLog(@"Input stream end encountered. Closing..."); + // Close the input stream once all the data has been read [aStream close]; [aStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; - break; - case NSStreamEventOpenCompleted: - // Todo - NSLog(@"Input stream open completed"); - case NSStreamEventHasBytesAvailable: - // Todo - NSLog(@"Input stream still reading"); - case NSStreamEventHasSpaceAvailable: - // Todo - NSLog(@"Input stream space still available"); - case NSStreamEventNone: - // Todo - NSLog(@"Input stream nothing happening"); default: break; } |
