Skip to content
This repository has been archived by the owner on Oct 6, 2024. It is now read-only.

Commit

Permalink
Fix: intermittent hangs when reading from API packet by using the BTF…
Browse files Browse the repository at this point in the history
…useStreamReader class
  • Loading branch information
breautek committed Jul 16, 2024
1 parent 285e6d8 commit b184820
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 7 deletions.
21 changes: 20 additions & 1 deletion BTFuse/BTFuse/BTFuseAPIPacket.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,31 @@ limitations under the License.

- (NSString*) getRoute;
- (BTFuseAPIClient*) getClient;
- (unsigned long) getContentLength;
- (uint64_t) getContentLength;
- (NSString*) getContentType;

/**
Reads the packet as a string.
Do not call on the main thread.
*/
- (NSString*) readAsString;

/**
Reads the packet as binary.
Do not call on the main thread.
*/
- (NSData*) readAsBinary;

/**
Reads the packet as a JSON/Dictionary object.
Do not call on the main thread.
*/
- (NSDictionary*) readAsJSONObject:(NSError*) error;

/**
Reads the packet as an array.
Do not call on the main thread.
*/
- (NSArray*) readAsJSONArray:(NSError*) error;

@end
Expand Down
52 changes: 47 additions & 5 deletions BTFuse/src/BTFuseAPIPacket.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,16 @@
#import <BTFuse/BTFuseAPIPacket.h>
#import <BTFuse/BTFuseContext.h>
#import <BTFuse/BTFuseLogger.h>
#import <BTFuse/BTFuseStreamReader.h>

const uint32_t BTFUSE_API_PACKET_BUFFER_SIZE = 1024 * 1024 * 4;

@implementation BTFuseAPIPacket {
NSString* $route;
BTFuseAPIClient* $client;
NSDictionary* $headers;
BTFuseContext* $context;
BTFuseStreamReader* $reader;
}

- (instancetype) init:(BTFuseContext*) context route:(NSString*) route headers:(NSDictionary*) headers client:(BTFuseAPIClient*) client {
Expand All @@ -33,6 +37,7 @@ - (instancetype) init:(BTFuseContext*) context route:(NSString*) route headers:(
$route = route;
$headers = headers;
$client = client;
$reader = [[BTFuseStreamReader alloc] init: [$client getInputStream]];

return self;
}
Expand All @@ -45,7 +50,7 @@ - (BTFuseAPIClient*) getClient {
return $client;
}

- (unsigned long) getContentLength {
- (uint64_t) getContentLength {
NSString* value = [$headers valueForKey: @"Content-Length"];
return value.longLongValue;
}
Expand All @@ -60,12 +65,49 @@ - (NSString*) readAsString {
}

- (NSData*) readAsBinary {
unsigned long contentLength = [self getContentLength];
uint64_t contentLength = [self getContentLength];
uint64_t totalBytesRead = 0;

NSMutableData* data = [[NSMutableData alloc] init];

uint32_t chunkSize = BTFUSE_API_PACKET_BUFFER_SIZE;
if (chunkSize > contentLength) {
chunkSize = (uint32_t) contentLength;
}

uint8_t buffer[chunkSize];
int64_t bytesRead = 0;

NSMutableData* buffer = [[NSMutableData alloc] init];
[$client read:buffer length: (uint32_t) contentLength];
while (true) {
uint64_t totalBytesToRead = contentLength - totalBytesRead;
if (totalBytesToRead == 0) {
break;
}

uint32_t bytesToRead = 0;
if (totalBytesToRead > UINT32_MAX) {
bytesToRead = UINT32_MAX;
}
else {
bytesToRead = (uint32_t) totalBytesToRead;
}

if (bytesToRead > chunkSize) {
bytesToRead = chunkSize;
}

bytesRead = [$reader read: buffer maxBytes: bytesToRead];

if (bytesRead == -1) {
NSLog(@"Socket Read Error");
return nil;
}

totalBytesRead += bytesRead;
[data appendBytes: buffer length: bytesRead];
}

return buffer;
return data;
}

- (NSDictionary*) readAsJSONObject:(NSError*) error {
Expand Down
2 changes: 1 addition & 1 deletion echo/echo/EchoPlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ - (void) initHandles {
}];

[self attachHandler:@"/threadtest" callback:^(BTFuseAPIPacket* packet, BTFuseAPIResponse* response) {
dispatch_async(dispatch_get_main_queue(), ^{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
[self doEcho: [packet readAsBinary] withResponse:response];
});
}];
Expand Down

0 comments on commit b184820

Please sign in to comment.