Skip to content

Commit

Permalink
Revert "Merge branch '781-mime-stream-pair' of git://github.com/plaus…
Browse files Browse the repository at this point in the history
…iblelabs/AFNetworking"

This reverts commit f7d98aa, reversing
changes made to 9b2a20c.

Conflicts:

	AFNetworking/AFHTTPClient.m
  • Loading branch information
mattt committed May 31, 2013
1 parent 7ed9b80 commit 8434140
Showing 1 changed file with 88 additions and 124 deletions.
212 changes: 88 additions & 124 deletions AFNetworking/AFHTTPClient.m
Original file line number Diff line number Diff line change
Expand Up @@ -801,8 +801,8 @@ - (NSInteger)read:(uint8_t *)buffer
maxLength:(NSUInteger)length;
@end

@interface AFMultipartBodyStreamProvider : NSObject
@property (nonatomic, assign) NSUInteger bufferLength;
@interface AFMultipartBodyStream : NSInputStream <NSStreamDelegate>
@property (nonatomic, assign) NSUInteger numberOfBytesInPacket;
@property (nonatomic, assign) NSTimeInterval delay;
@property (nonatomic, strong) NSInputStream *inputStream;
@property (nonatomic, readonly) unsigned long long contentLength;
Expand All @@ -817,7 +817,7 @@ - (void)appendHTTPBodyPart:(AFHTTPBodyPart *)bodyPart;

@interface AFStreamingMultipartFormData ()
@property (readwrite, nonatomic, copy) NSMutableURLRequest *request;
@property (readwrite, nonatomic, strong) AFMultipartBodyStreamProvider *bodyStream;
@property (readwrite, nonatomic, strong) AFMultipartBodyStream *bodyStream;
@property (readwrite, nonatomic, assign) NSStringEncoding stringEncoding;
@end

Expand All @@ -836,7 +836,7 @@ - (id)initWithURLRequest:(NSMutableURLRequest *)urlRequest

self.request = urlRequest;
self.stringEncoding = encoding;
self.bodyStream = [[AFMultipartBodyStreamProvider alloc] initWithStringEncoding:encoding];
self.bodyStream = [[AFMultipartBodyStream alloc] initWithStringEncoding:encoding];

return self;
}
Expand Down Expand Up @@ -968,7 +968,7 @@ - (void)appendPartWithHeaders:(NSDictionary *)headers
- (void)throttleBandwidthWithPacketSize:(NSUInteger)numberOfBytes
delay:(NSTimeInterval)delay
{
self.bodyStream.bufferLength = numberOfBytes;
self.bodyStream.numberOfBytesInPacket = numberOfBytes;
self.bodyStream.delay = delay;
}

Expand All @@ -982,7 +982,7 @@ - (NSMutableURLRequest *)requestByFinalizingMultipartFormData {

[self.request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", kAFMultipartFormBoundary] forHTTPHeaderField:@"Content-Type"];
[self.request setValue:[NSString stringWithFormat:@"%llu", [self.bodyStream contentLength]] forHTTPHeaderField:@"Content-Length"];
[self.request setHTTPBodyStream:self.bodyStream.inputStream];
[self.request setHTTPBodyStream:self.bodyStream];

return self.request;
}
Expand All @@ -991,7 +991,9 @@ - (NSMutableURLRequest *)requestByFinalizingMultipartFormData {

#pragma mark -

@interface AFMultipartBodyStreamProvider () <NSCopying, NSStreamDelegate>
@interface AFMultipartBodyStream () <NSCopying>
@property (nonatomic, assign) NSStreamStatus streamStatus;
@property (nonatomic, strong) NSError *streamError;
@property (nonatomic, assign) NSStringEncoding stringEncoding;
@property (nonatomic, strong) NSMutableArray *HTTPBodyParts;
@property (nonatomic, strong) NSEnumerator *HTTPBodyPartEnumerator;
Expand All @@ -1000,21 +1002,17 @@ @interface AFMultipartBodyStreamProvider () <NSCopying, NSStreamDelegate>
@property (nonatomic, strong) NSMutableData *buffer;
@end

static const NSUInteger AFMultipartBodyStreamProviderDefaultBufferLength = 4096;

@implementation AFMultipartBodyStreamProvider {
@private
// Workaround for stream delegates being weakly referenced, but otherwise unowned
__strong id _self;
}
@implementation AFMultipartBodyStream
@synthesize streamStatus = _streamStatus;
@synthesize streamError = _streamError;
@synthesize stringEncoding = _stringEncoding;
@synthesize HTTPBodyParts = _HTTPBodyParts;
@synthesize HTTPBodyPartEnumerator = _HTTPBodyPartEnumerator;
@synthesize currentHTTPBodyPart = _currentHTTPBodyPart;
@synthesize inputStream = _inputStream;
@synthesize outputStream = _outputStream;
@synthesize buffer = _buffer;
@synthesize bufferLength = _numberOfBytesInPacket;
@synthesize numberOfBytesInPacket = _numberOfBytesInPacket;
@synthesize delay = _delay;

- (id)initWithStringEncoding:(NSStringEncoding)encoding {
Expand All @@ -1025,16 +1023,9 @@ - (id)initWithStringEncoding:(NSStringEncoding)encoding {

self.stringEncoding = encoding;
self.HTTPBodyParts = [NSMutableArray array];
self.bufferLength = NSIntegerMax;

self.buffer = [[NSMutableData alloc] init];
self.bufferLength = AFMultipartBodyStreamProviderDefaultBufferLength;

return self;
}
self.numberOfBytesInPacket = NSIntegerMax;

- (void)dealloc {
_outputStream.delegate = nil;
return self;
}

- (void)setInitialAndFinalBoundaries {
Expand All @@ -1053,116 +1044,80 @@ - (void)appendHTTPBodyPart:(AFHTTPBodyPart *)bodyPart {
[self.HTTPBodyParts addObject:bodyPart];
}

- (NSInputStream *)inputStream {
if (_inputStream == nil) {
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreateBoundPair(NULL, &readStream, &writeStream, (NSInteger)self.bufferLength);
_inputStream = CFBridgingRelease(readStream);
_outputStream = CFBridgingRelease(writeStream);

_outputStream.delegate = self;
if ([NSThread isMainThread]) {
[_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
} else {
dispatch_sync(dispatch_get_main_queue(), ^{
[_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
});
}
[_outputStream open];

_self = self;
}

return _inputStream;
}

- (BOOL)isEmpty {
return [self.HTTPBodyParts count] == 0;
}

#pragma mark - NSStreamDelegate
#pragma mark - NSInputStream

- (NSInteger)read:(uint8_t *)buffer
maxLength:(NSUInteger)length
{
if ([self streamStatus] == NSStreamStatusClosed) {
return 0;
}
NSInteger bytesRead = 0;

// This retry works around a nasty problem in which mutli-part uploads will fail due to the stream delegate being sent a `NSStreamEventHasSpaceAvailable` event before the input stream has finished opening.
// This workaround simply replays the event after allowing the run-loop to cycle, providing enough time for the input stream to finish opening. It appears that this bug is in the CFNetwork layer.
// See: https://github.com/AFNetworking/AFNetworking/issues/948
- (void)retryWrite:(NSStream *)stream {
[self stream:stream handleEvent:NSStreamEventHasSpaceAvailable];
}

- (void)stream:(NSStream *)stream
handleEvent:(NSStreamEvent)eventCode {
if (eventCode & NSStreamEventHasSpaceAvailable) {
if (self.inputStream.streamStatus < NSStreamStatusOpen) {
[self performSelector:@selector(retryWrite:) withObject:stream afterDelay:0.1];
while ((NSUInteger)bytesRead < MIN(length, self.numberOfBytesInPacket)) {
if (!self.currentHTTPBodyPart || ![self.currentHTTPBodyPart hasBytesAvailable]) {
if (!(self.currentHTTPBodyPart = [self.HTTPBodyPartEnumerator nextObject])) {
break;
}
} else {
[self handleOutputStreamSpaceAvailable];
bytesRead += [self.currentHTTPBodyPart read:&buffer[bytesRead] maxLength:(length - (NSUInteger)bytesRead)];
if (self.delay > 0.0f) {
[NSThread sleepForTimeInterval:self.delay];
}
}
}
return bytesRead;
}

- (void)handleOutputStreamSpaceAvailable {
while ([_outputStream hasSpaceAvailable]) {
if ([_buffer length] > 0) {
NSInteger numberOfBytesWritten = [_outputStream write:(uint8_t const *)[_buffer bytes] maxLength:[_buffer length]];
if (numberOfBytesWritten < 0) {
[self close];
return;
}
- (BOOL)getBuffer:(__unused uint8_t **)buffer
length:(__unused NSUInteger *)len
{
return NO;
}

[_buffer replaceBytesInRange:NSMakeRange(0, (NSUInteger)numberOfBytesWritten) withBytes:NULL length:0];
} else {
if (!self.currentHTTPBodyPart) {
if (!self.HTTPBodyPartEnumerator) {
self.HTTPBodyPartEnumerator = [self.HTTPBodyParts objectEnumerator];
}
self.currentHTTPBodyPart = [self.HTTPBodyPartEnumerator nextObject];
}

if (!self.currentHTTPBodyPart) {
[self close];
return;
}

[_buffer setLength:self.bufferLength];

NSInteger numberOfBytesRead = [self.currentHTTPBodyPart read:(uint8_t *)[_buffer mutableBytes] maxLength:[_buffer length]];
if (numberOfBytesRead < 0) {
[self close];
return;
}

[_buffer setLength:(NSUInteger)numberOfBytesRead];
- (BOOL)hasBytesAvailable {
return [self streamStatus] == NSStreamStatusOpen;
}

if (numberOfBytesRead == 0) {
self.currentHTTPBodyPart = nil;
}
#pragma mark - NSStream

if (self.delay > 0.0f) {
[NSThread sleepForTimeInterval:self.delay];
}
}
- (void)open {
if (self.streamStatus == NSStreamStatusOpen) {
return;
}

self.streamStatus = NSStreamStatusOpen;

[self setInitialAndFinalBoundaries];
self.HTTPBodyPartEnumerator = [self.HTTPBodyParts objectEnumerator];
}

- (void)close {
NSOutputStream *outputStream = self.outputStream;

[outputStream close];
outputStream.delegate = nil;

// Workaround for a race condition in CFStream _CFStreamCopyRunLoopsAndModes. This outputstream needs to be retained just a little longer.
// See: https://github.com/AFNetworking/AFNetworking/issues/907
NSTimeInterval delay = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^{
outputStream.delegate = nil;
});

_self = nil;
self.streamStatus = NSStreamStatusClosed;
}

- (id)propertyForKey:(__unused NSString *)key {
return nil;
}

- (BOOL)setProperty:(__unused id)property
forKey:(__unused NSString *)key
{
return NO;
}

- (void)scheduleInRunLoop:(__unused NSRunLoop *)aRunLoop
forMode:(__unused NSString *)mode
{}

- (void)removeFromRunLoop:(__unused NSRunLoop *)aRunLoop
forMode:(__unused NSString *)mode
{}

- (unsigned long long)contentLength {
unsigned long long length = 0;
for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) {
Expand All @@ -1172,10 +1127,26 @@ - (unsigned long long)contentLength {
return length;
}

#pragma mark - Undocumented CFReadStream Bridged Methods

- (void)_scheduleInCFRunLoop:(__unused CFRunLoopRef)aRunLoop
forMode:(__unused CFStringRef)aMode
{}

- (void)_unscheduleFromCFRunLoop:(__unused CFRunLoopRef)aRunLoop
forMode:(__unused CFStringRef)aMode
{}

- (BOOL)_setCFClientFlags:(__unused CFOptionFlags)inFlags
callback:(__unused CFReadStreamClientCallBack)inCallback
context:(__unused CFStreamClientContext *)inContext {
return NO;
}

#pragma mark - NSCopying

- (id)copyWithZone:(NSZone *)zone {
AFMultipartBodyStreamProvider *bodyStreamCopy = [[[self class] allocWithZone:zone] initWithStringEncoding:self.stringEncoding];
-(id)copyWithZone:(NSZone *)zone {
AFMultipartBodyStream *bodyStreamCopy = [[[self class] allocWithZone:zone] initWithStringEncoding:self.stringEncoding];

for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) {
[bodyStreamCopy appendHTTPBodyPart:[bodyPart copy]];
Expand All @@ -1191,12 +1162,10 @@ - (id)copyWithZone:(NSZone *)zone {
#pragma mark -

typedef enum {
AFInitialPhase = 0,
AFEncapsulationBoundaryPhase = 1,
AFHeaderPhase = 2,
AFBodyPhase = 3,
AFFinalBoundaryPhase = 4,
AFCompletedPhase = 5,
} AFHTTPBodyPartReadPhase;

@interface AFHTTPBodyPart () <NSCopying> {
Expand Down Expand Up @@ -1301,7 +1270,6 @@ - (BOOL)hasBytesAvailable {
return NO;
}
#pragma clang diagnostic pop

}

- (NSInteger)read:(uint8_t *)buffer
Expand Down Expand Up @@ -1365,9 +1333,6 @@ - (BOOL)transitionToNextPhase {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wcovered-switch-default"
switch (_phase) {
case AFInitialPhase:
_phase = AFEncapsulationBoundaryPhase;
break;
case AFEncapsulationBoundaryPhase:
_phase = AFHeaderPhase;
break;
Expand All @@ -1381,9 +1346,8 @@ - (BOOL)transitionToNextPhase {
_phase = AFFinalBoundaryPhase;
break;
case AFFinalBoundaryPhase:
case AFCompletedPhase:
default:
_phase = AFCompletedPhase;
_phase = AFEncapsulationBoundaryPhase;
break;
}
_phaseReadOffset = 0;
Expand Down

0 comments on commit 8434140

Please sign in to comment.