aboutsummaryrefslogtreecommitdiffhomepage
path: root/Firebase/Database/third_party/SocketRocket/FSRWebSocket.m
diff options
context:
space:
mode:
Diffstat (limited to 'Firebase/Database/third_party/SocketRocket/FSRWebSocket.m')
-rw-r--r--Firebase/Database/third_party/SocketRocket/FSRWebSocket.m352
1 files changed, 176 insertions, 176 deletions
diff --git a/Firebase/Database/third_party/SocketRocket/FSRWebSocket.m b/Firebase/Database/third_party/SocketRocket/FSRWebSocket.m
index f96d863..a2c857b 100644
--- a/Firebase/Database/third_party/SocketRocket/FSRWebSocket.m
+++ b/Firebase/Database/third_party/SocketRocket/FSRWebSocket.m
@@ -52,7 +52,7 @@
typedef enum {
SROpCodeTextFrame = 0x1,
SROpCodeBinaryFrame = 0x2,
- //3-7Reserved
+ //3-7Reserved
SROpCodeConnectionClose = 0x8,
SROpCodePing = 0x9,
SROpCodePong = 0xA,
@@ -117,13 +117,13 @@ static inline void SRFastLog(NSString *format, ...);
static NSString *newSHA1String(const char *bytes, size_t length) {
uint8_t md[CC_SHA1_DIGEST_LENGTH];
-
+
CC_SHA1(bytes, (int)length, md);
-
+
size_t buffer_size = ((sizeof(md) * 3 + 2) / 2);
-
+
char *buffer = (char *)malloc(buffer_size);
-
+
int len = f_b64_ntop(md, CC_SHA1_DIGEST_LENGTH, buffer, buffer_size);
if (len == -1) {
free(buffer);
@@ -232,10 +232,10 @@ typedef void (^data_callback)(FSRWebSocket *webSocket, NSData *data);
NSInputStream *_inputStream;
NSOutputStream *_outputStream;
-
+
NSMutableData *_readBuffer;
NSInteger _readBufferOffset;
-
+
NSMutableData *_outputBuffer;
NSInteger _outputBufferOffset;
@@ -244,18 +244,18 @@ typedef void (^data_callback)(FSRWebSocket *webSocket, NSData *data);
size_t _readOpCount;
uint32_t _currentStringScanPosition;
NSMutableData *_currentFrameData;
-
+
NSString *_closeReason;
-
+
NSString *_secKey;
-
+
BOOL _pinnedCertFound;
-
+
uint8_t _currentReadMaskKey[4];
size_t _currentReadMaskOffset;
BOOL _consumerStopped;
-
+
BOOL _closeWhenFinishedWriting;
BOOL _failed;
@@ -264,19 +264,19 @@ typedef void (^data_callback)(FSRWebSocket *webSocket, NSData *data);
NSString *_userAgent;
CFHTTPMessageRef _receivedHTTPHeaders;
-
+
BOOL _sentClose;
BOOL _didFail;
BOOL _cleanupScheduled;
int _closeCode;
-
+
BOOL _isPumping;
NSMutableSet *_scheduledRunloops;
-
+
// We use this to retain ourselves.
__strong FSRWebSocket *_selfRetain;
-
+
NSArray *_requestedProtocols;
FSRIOConsumerPool *_consumerPool;
}
@@ -300,26 +300,26 @@ static __strong NSData *CRLFCRLF;
assert(request.URL);
_url = request.URL;
NSString *scheme = [_url scheme];
-
+
_requestedProtocols = [protocols copy];
_userAgent = userAgent;
assert([scheme isEqualToString:@"ws"] || [scheme isEqualToString:@"http"] || [scheme isEqualToString:@"wss"] || [scheme isEqualToString:@"https"]);
_urlRequest = request;
-
+
if ([scheme isEqualToString:@"wss"] || [scheme isEqualToString:@"https"]) {
_secure = YES;
}
-
+
if (!queue) {
_delegateDispatchQueue = dispatch_get_main_queue();
} else {
_delegateDispatchQueue = queue;
}
-
+
[self _SR_commonInit];
}
-
+
return self;
}
@@ -345,7 +345,7 @@ static __strong NSData *CRLFCRLF;
- (id)initWithURL:(NSURL *)url protocols:(NSArray *)protocols;
{
- NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
+ NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
return [self initWithURLRequest:request protocols:protocols];
}
@@ -354,9 +354,9 @@ static __strong NSData *CRLFCRLF;
_readyState = SR_CONNECTING;
_consumerStopped = YES;
-
+
_webSocketVersion = 13;
-
+
_workQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
// Going to set a specific on the queue so we can validate we're on the work queue
@@ -366,7 +366,7 @@ static __strong NSData *CRLFCRLF;
_readBuffer = [[NSMutableData alloc] init];
_outputBuffer = [[NSMutableData alloc] init];
-
+
_currentFrameData = [[NSMutableData alloc] init];
_consumers = [[NSMutableArray alloc] init];
@@ -376,7 +376,7 @@ static __strong NSData *CRLFCRLF;
_scheduledRunloops = [[NSMutableSet alloc] init];
[self _initializeStreams];
-
+
// default handlers
}
@@ -395,7 +395,7 @@ static __strong NSData *CRLFCRLF;
sr_dispatch_release(_workQueue);
_workQueue = NULL;
-
+
if (_receivedHTTPHeaders) {
CFRelease(_receivedHTTPHeaders);
_receivedHTTPHeaders = NULL;
@@ -460,29 +460,29 @@ static __strong NSData *CRLFCRLF;
if (acceptHeader == nil) {
return NO;
}
-
+
NSString *concattedString = [_secKey stringByAppendingString:SRWebSocketAppendToSecKeyString];
NSString *expectedAccept = [concattedString stringBySHA1ThenBase64Encoding];
-
+
return [acceptHeader isEqualToString:expectedAccept];
}
- (void)_HTTPHeadersDidFinish;
{
NSInteger responseCode = CFHTTPMessageGetResponseStatusCode(_receivedHTTPHeaders);
-
+
if (responseCode >= 400) {
SRFastLog(@"Request failed with response code %d", responseCode);
[self _failWithError:[NSError errorWithDomain:@"org.lolrus.SocketRocket" code:2132 userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"received bad response code from server %u", (int)responseCode] forKey:NSLocalizedDescriptionKey]]];
return;
}
-
+
if(![self _checkHandshake:_receivedHTTPHeaders]) {
[self _failWithError:[NSError errorWithDomain:FSRWebSocketErrorDomain code:2133 userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"Invalid Sec-WebSocket-Accept response"] forKey:NSLocalizedDescriptionKey]]];
return;
}
-
+
NSString *negotiatedProtocol = CFBridgingRelease(CFHTTPMessageCopyHeaderFieldValue(_receivedHTTPHeaders, CFSTR("Sec-WebSocket-Protocol")));
if (negotiatedProtocol) {
// Make sure we requested the protocol
@@ -490,12 +490,12 @@ static __strong NSData *CRLFCRLF;
[self _failWithError:[NSError errorWithDomain:FSRWebSocketErrorDomain code:2133 userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"Server specified Sec-WebSocket-Protocol that wasn't requested"] forKey:NSLocalizedDescriptionKey]]];
return;
}
-
+
_protocol = negotiatedProtocol;
}
-
+
self.readyState = SR_OPEN;
-
+
if (!_didFail) {
[self _readFrameNew];
}
@@ -513,10 +513,10 @@ static __strong NSData *CRLFCRLF;
if (_receivedHTTPHeaders == NULL) {
_receivedHTTPHeaders = CFHTTPMessageCreateEmpty(NULL, NO);
}
-
+
[self _readUntilHeaderCompleteWithCallback:^(FSRWebSocket *self, NSData *data) {
CFHTTPMessageAppendBytes(_receivedHTTPHeaders, (const UInt8 *)data.bytes, data.length);
-
+
if (CFHTTPMessageIsHeaderComplete(_receivedHTTPHeaders)) {
SRFastLog(@"Finished reading headers %@", CFBridgingRelease(CFHTTPMessageCopyAllHeaderFields(_receivedHTTPHeaders)));
[self _HTTPHeadersDidFinish];
@@ -530,16 +530,16 @@ static __strong NSData *CRLFCRLF;
{
SRFastLog(@"Connected");
CFHTTPMessageRef request = CFHTTPMessageCreateRequest(NULL, CFSTR("GET"), (__bridge CFURLRef)_url, kCFHTTPVersion1_1);
-
+
// Set host first so it defaults
CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Host"), (__bridge CFStringRef)(_url.port ? [NSString stringWithFormat:@"%@:%@", _url.host, _url.port] : _url.host));
-
+
NSMutableData *keyBytes = [[NSMutableData alloc] initWithLength:16];
int result = SecRandomCopyBytes(kSecRandomDefault, keyBytes.length, keyBytes.mutableBytes);
assert(result == 0);
_secKey = [FSRUtilities base64EncodedStringFromData:keyBytes];
assert([_secKey length] == 24);
-
+
CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Upgrade"), CFSTR("websocket"));
CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Connection"), CFSTR("Upgrade"));
if (_userAgent) {
@@ -548,9 +548,9 @@ static __strong NSData *CRLFCRLF;
CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Sec-WebSocket-Key"), (__bridge CFStringRef)_secKey);
CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Sec-WebSocket-Version"), (__bridge CFStringRef)[NSString stringWithFormat:@"%u", (int)_webSocketVersion]);
-
+
CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Origin"), (__bridge CFStringRef)_url.SR_origin);
-
+
if (_requestedProtocols) {
CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Sec-WebSocket-Protocol"), (__bridge CFStringRef)[_requestedProtocols componentsJoinedByString:@", "]);
}
@@ -558,9 +558,9 @@ static __strong NSData *CRLFCRLF;
[_urlRequest.allHTTPHeaderFields enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
CFHTTPMessageSetHeaderFieldValue(request, (__bridge CFStringRef)key, (__bridge CFStringRef)obj);
}];
-
+
NSData *message = CFBridgingRelease(CFHTTPMessageCopySerializedMessage(request));
-
+
CFRelease(request);
[self _writeData:message];
@@ -582,34 +582,34 @@ static __strong NSData *CRLFCRLF;
CFReadStreamRef readStream = NULL;
CFWriteStreamRef writeStream = NULL;
-
+
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)host, (int)port, &readStream, &writeStream);
-
+
// XXX
CFReadStreamSetProperty(readStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeBackground);
CFWriteStreamSetProperty(writeStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeBackground);
-
+
_outputStream = CFBridgingRelease(writeStream);
_inputStream = CFBridgingRelease(readStream);
-
-
+
+
if (_secure) {
NSMutableDictionary *SSLOptions = [[NSMutableDictionary alloc] init];
-
+
[_outputStream setProperty:(__bridge id)kCFStreamSocketSecurityLevelNegotiatedSSL forKey:(__bridge id)kCFStreamPropertySocketSecurityLevel];
-
+
// If we're using pinned certs, don't validate the certificate chain
if ([_urlRequest FSR_SSLPinnedCertificates].count) {
[SSLOptions setValue:[NSNumber numberWithBool:NO] forKey:(__bridge id)kCFStreamSSLValidatesCertificateChain];
}
-
+
[_outputStream setProperty:SSLOptions
forKey:(__bridge id)kCFStreamPropertySSLSettings];
}
-
+
_inputStream.delegate = self;
_outputStream.delegate = self;
-
+
[_outputStream open];
[_inputStream open];
}
@@ -653,7 +653,7 @@ static __strong NSData *CRLFCRLF;
if (self.readyState == SR_CLOSING || self.readyState == SR_CLOSED) {
return;
}
-
+
BOOL wasConnecting = self.readyState == SR_CONNECTING;
self.readyState = SR_CLOSING;
@@ -668,16 +668,16 @@ static __strong NSData *CRLFCRLF;
size_t maxMsgSize = [reason maximumLengthOfBytesUsingEncoding:NSUTF8StringEncoding];
NSMutableData *mutablePayload = [[NSMutableData alloc] initWithLength:sizeof(uint16_t) + maxMsgSize];
NSData *payload = mutablePayload;
-
+
((uint16_t *)mutablePayload.mutableBytes)[0] = EndianU16_BtoN(code);
-
+
if (reason) {
NSRange remainingRange = {0};
-
+
NSUInteger usedLength = 0;
-
+
BOOL success = [reason getBytes:(char *)mutablePayload.mutableBytes + sizeof(uint16_t) maxLength:payload.length - sizeof(uint16_t) usedLength:&usedLength encoding:NSUTF8StringEncoding options:NSStringEncodingConversionExternalRepresentation range:NSMakeRange(0, reason.length) remainingRange:&remainingRange];
-
+
assert(success);
assert(remainingRange.length == 0);
@@ -685,15 +685,15 @@ static __strong NSData *CRLFCRLF;
payload = [payload subdataWithRange:NSMakeRange(0, usedLength + sizeof(uint16_t))];
}
}
-
-
+
+
[self _sendFrameWithOpcode:SROpCodeConnectionClose data:payload];
});
}
- (void)_closeWithProtocolError:(NSString *)message;
{
- // Need to shunt this on the _callbackQueue first to see if they received any messages
+ // Need to shunt this on the _callbackQueue first to see if they received any messages
[self _performDelegateBlock:^{
[self closeWithCode:SRStatusCodeProtocolError reason:message];
dispatch_async(_workQueue, ^{
@@ -716,7 +716,7 @@ static __strong NSData *CRLFCRLF;
self.readyState = SR_CLOSED;
SRFastLog(@"Failing with error %@", error.localizedDescription);
-
+
[self _disconnect];
[self _scheduleCleanup];
}
@@ -724,7 +724,7 @@ static __strong NSData *CRLFCRLF;
}
- (void)_writeData:(NSData *)data;
-{
+{
[self assertOnWorkQueue];
if (_closeWhenFinishedWriting) {
@@ -782,7 +782,7 @@ static inline BOOL closeCodeIsValid(int closeCode) {
if (closeCode < 1000) {
return NO;
}
-
+
if (closeCode >= 1000 && closeCode <= 1011) {
if (closeCode == 1004 ||
closeCode == 1005 ||
@@ -791,11 +791,11 @@ static inline BOOL closeCodeIsValid(int closeCode) {
}
return YES;
}
-
+
if (closeCode >= 3000 && closeCode <= 3999) {
return YES;
}
-
+
if (closeCode >= 4000 && closeCode <= 4999) {
return YES;
}
@@ -816,9 +816,9 @@ static inline BOOL closeCodeIsValid(int closeCode) {
{
size_t dataSize = data.length;
__block uint16_t closeCode = 0;
-
+
SRFastLog(@"Received close frame");
-
+
if (dataSize == 1) {
// TODO handle error
[self _closeWithProtocolError:@"Payload for close must be larger than 2 bytes"];
@@ -840,9 +840,9 @@ static inline BOOL closeCodeIsValid(int closeCode) {
} else {
_closeCode = SRStatusNoStatusReceived;
}
-
+
[self assertOnWorkQueue];
-
+
if (self.readyState == SR_OPEN) {
[self closeWithCode:1000 reason:nil];
}
@@ -860,9 +860,9 @@ static inline BOOL closeCodeIsValid(int closeCode) {
}
- (void)_handleFrameWithData:(NSData *)frameData opCode:(NSInteger)opcode;
-{
+{
// Check that the current data is valid UTF8
-
+
BOOL isControlFrame = (opcode == SROpCodePing || opcode == SROpCodePong || opcode == SROpCodeConnectionClose);
if (!isControlFrame) {
[self _readFrameNew];
@@ -871,7 +871,7 @@ static inline BOOL closeCodeIsValid(int closeCode) {
[self _readFrameContinue];
});
}
-
+
switch (opcode) {
case SROpCodeTextFrame: {
NSString *str = [[NSString alloc] initWithData:frameData encoding:NSUTF8StringEncoding];
@@ -908,29 +908,29 @@ static inline BOOL closeCodeIsValid(int closeCode) {
- (void)_handleFrameHeader:(frame_header)frame_header curData:(NSData *)curData;
{
assert(frame_header.opcode != 0);
-
+
if (self.readyState != SR_OPEN) {
return;
}
-
-
+
+
BOOL isControlFrame = (frame_header.opcode == SROpCodePing || frame_header.opcode == SROpCodePong || frame_header.opcode == SROpCodeConnectionClose);
-
+
if (isControlFrame && !frame_header.fin) {
[self _closeWithProtocolError:@"Fragmented control frames not allowed"];
return;
}
-
+
if (isControlFrame && frame_header.payload_length >= 126) {
[self _closeWithProtocolError:@"Control frames cannot have payloads larger than 126 bytes"];
return;
}
-
+
if (!isControlFrame) {
_currentFrameOpcode = frame_header.opcode;
_currentFrameCount += 1;
}
-
+
if (frame_header.payload_length == 0) {
if (isControlFrame) {
[self _handleFrameWithData:curData opCode:frame_header.opcode];
@@ -953,7 +953,7 @@ static inline BOOL closeCodeIsValid(int closeCode) {
// TODO add assert that opcode is not a control;
[self _readFrameContinue];
}
-
+
}
} readToCurrentFrame:!isControlFrame unmaskBytes:frame_header.masked];
}
@@ -994,51 +994,51 @@ static const uint8_t SRPayloadLenMask = 0x7F;
[self _addConsumerWithDataLength:2 callback:^(FSRWebSocket *self, NSData *data) {
__block frame_header header = {0};
-
+
const uint8_t *headerBuffer = data.bytes;
assert(data.length >= 2);
-
+
if (headerBuffer[0] & SRRsvMask) {
[self _closeWithProtocolError:@"Server used RSV bits"];
return;
}
-
+
uint8_t receivedOpcode = (SROpCodeMask & headerBuffer[0]);
-
+
BOOL isControlFrame = (receivedOpcode == SROpCodePing || receivedOpcode == SROpCodePong || receivedOpcode == SROpCodeConnectionClose);
-
+
if (!isControlFrame && receivedOpcode != 0 && self->_currentFrameCount > 0) {
[self _closeWithProtocolError:@"all data frames after the initial data frame must have opcode 0"];
return;
}
-
+
if (receivedOpcode == 0 && self->_currentFrameCount == 0) {
[self _closeWithProtocolError:@"cannot continue a message"];
return;
}
-
+
header.opcode = receivedOpcode == 0 ? self->_currentFrameOpcode : receivedOpcode;
-
+
header.fin = !!(SRFinMask & headerBuffer[0]);
-
-
+
+
header.masked = !!(SRMaskMask & headerBuffer[1]);
header.payload_length = SRPayloadLenMask & headerBuffer[1];
-
+
headerBuffer = NULL;
-
+
if (header.masked) {
[self _closeWithProtocolError:@"Client must receive unmasked data"];
}
-
+
size_t extra_bytes_needed = header.masked ? sizeof(_currentReadMaskKey) : 0;
-
+
if (header.payload_length == 126) {
extra_bytes_needed += sizeof(uint16_t);
} else if (header.payload_length == 127) {
extra_bytes_needed += sizeof(uint64_t);
}
-
+
if (extra_bytes_needed == 0) {
[self _handleFrameHeader:header curData:self->_currentFrameData];
} else {
@@ -1046,7 +1046,7 @@ static const uint8_t SRPayloadLenMask = 0x7F;
size_t mapped_size = data.length;
const void *mapped_buffer = data.bytes;
size_t offset = 0;
-
+
if (header.payload_length == 126) {
assert(mapped_size >= sizeof(uint16_t));
uint16_t newLen = EndianU16_BtoN(*(uint16_t *)(mapped_buffer));
@@ -1059,13 +1059,13 @@ static const uint8_t SRPayloadLenMask = 0x7F;
} else {
assert(header.payload_length < 126 && header.payload_length >= 0);
}
-
-
+
+
if (header.masked) {
assert(mapped_size >= sizeof(_currentReadMaskOffset) + offset);
memcpy(self->_currentReadMaskKey, ((uint8_t *)mapped_buffer) + offset, sizeof(self->_currentReadMaskKey));
}
-
+
[self _handleFrameHeader:header curData:self->_currentFrameData];
} readToCurrentFrame:NO unmaskBytes:NO];
}
@@ -1076,12 +1076,12 @@ static const uint8_t SRPayloadLenMask = 0x7F;
{
dispatch_async(_workQueue, ^{
[_currentFrameData setLength:0];
-
+
_currentFrameOpcode = 0;
_currentFrameCount = 0;
_readOpCount = 0;
_currentStringScanPosition = 0;
-
+
[self _readFrameContinue];
});
}
@@ -1097,17 +1097,17 @@ static const uint8_t SRPayloadLenMask = 0x7F;
[self _failWithError:[NSError errorWithDomain:@"org.lolrus.SocketRocket" code:2145 userInfo:[NSDictionary dictionaryWithObject:@"Error writing to stream" forKey:NSLocalizedDescriptionKey]]];
return;
}
-
+
_outputBufferOffset += bytesWritten;
-
+
if (_outputBufferOffset > 4096 && _outputBufferOffset > (_outputBuffer.length >> 1)) {
_outputBuffer = [[NSMutableData alloc] initWithBytes:(char *)_outputBuffer.bytes + _outputBufferOffset length:_outputBuffer.length - _outputBufferOffset];
_outputBufferOffset = 0;
}
}
-
- if (_closeWhenFinishedWriting &&
- _outputBuffer.length - _outputBufferOffset == 0 &&
+
+ if (_closeWhenFinishedWriting &&
+ _outputBuffer.length - _outputBufferOffset == 0 &&
(_inputStream.streamStatus != NSStreamStatusNotOpen &&
_inputStream.streamStatus != NSStreamStatusClosed) &&
!_sentClose) {
@@ -1119,7 +1119,7 @@ static const uint8_t SRPayloadLenMask = 0x7F;
// TODO: Why are we missing the SocketRocket code to call unscheduleFromRunLoop???
}
-
+
if (!_failed) {
[self _performDelegateBlock:^{
if ([self.delegate respondsToSelector:@selector(webSocket:didCloseWithCode:reason:wasClean:)]) {
@@ -1138,7 +1138,7 @@ static const uint8_t SRPayloadLenMask = 0x7F;
}
- (void)_addConsumerWithDataLength:(size_t)dataLength callback:(data_callback)callback readToCurrentFrame:(BOOL)readToCurrentFrame unmaskBytes:(BOOL)unmaskBytes;
-{
+{
[self assertOnWorkQueue];
assert(dataLength);
@@ -1147,7 +1147,7 @@ static const uint8_t SRPayloadLenMask = 0x7F;
}
- (void)_addConsumerWithScanner:(stream_scanner)consumer callback:(data_callback)callback dataLength:(size_t)dataLength;
-{
+{
[self assertOnWorkQueue];
[_consumers addObject:[_consumerPool consumerWithScanner:consumer handler:callback bytesNeeded:dataLength readToCurrentFrame:NO unmaskBytes:NO]];
[self _pumpScanner];
@@ -1202,7 +1202,7 @@ static const char CRLFCRLFBytes[] = {'\r', '\n', '\r', '\n'};
stream_scanner consumer = ^size_t(NSData *data) {
__block size_t found_size = 0;
__block size_t match_count = 0;
-
+
size_t size = data.length;
const unsigned char *buffer = data.bytes;
for (int i = 0; i < size; i++ ) {
@@ -1224,29 +1224,29 @@ static const char CRLFCRLFBytes[] = {'\r', '\n', '\r', '\n'};
// Returns true if did work
- (BOOL)_innerPumpScanner {
-
+
BOOL didWork = NO;
-
+
if (self.readyState >= SR_CLOSING) {
return didWork;
}
-
+
if (!_consumers.count) {
return didWork;
}
-
+
size_t curSize = _readBuffer.length - _readBufferOffset;
if (!curSize) {
return didWork;
}
-
+
FSRIOConsumer *consumer = [_consumers objectAtIndex:0];
-
+
size_t bytesNeeded = consumer.bytesNeeded;
-
+
size_t foundSize = 0;
if (consumer.consumer) {
- NSData *tempView = [NSData dataWithBytesNoCopy:(char *)_readBuffer.bytes + _readBufferOffset length:_readBuffer.length - _readBufferOffset freeWhenDone:NO];
+ NSData *tempView = [NSData dataWithBytesNoCopy:(char *)_readBuffer.bytes + _readBufferOffset length:_readBuffer.length - _readBufferOffset freeWhenDone:NO];
foundSize = consumer.consumer(tempView);
} else {
assert(consumer.bytesNeeded);
@@ -1256,48 +1256,48 @@ static const char CRLFCRLFBytes[] = {'\r', '\n', '\r', '\n'};
foundSize = curSize;
}
}
-
+
NSData *slice = nil;
if (consumer.readToCurrentFrame || foundSize) {
NSRange sliceRange = NSMakeRange(_readBufferOffset, foundSize);
slice = [_readBuffer subdataWithRange:sliceRange];
-
+
_readBufferOffset += foundSize;
-
+
if (_readBufferOffset > 4096 && _readBufferOffset > (_readBuffer.length >> 1)) {
_readBuffer = [[NSMutableData alloc] initWithBytes:(char *)_readBuffer.bytes + _readBufferOffset length:_readBuffer.length - _readBufferOffset]; _readBufferOffset = 0;
}
-
+
if (consumer.unmaskBytes) {
NSMutableData *mutableSlice = [slice mutableCopy];
-
+
NSUInteger len = mutableSlice.length;
uint8_t *bytes = mutableSlice.mutableBytes;
-
+
for (int i = 0; i < len; i++) {
bytes[i] = bytes[i] ^ _currentReadMaskKey[_currentReadMaskOffset % sizeof(_currentReadMaskKey)];
_currentReadMaskOffset += 1;
}
-
+
slice = mutableSlice;
}
-
+
if (consumer.readToCurrentFrame) {
[_currentFrameData appendData:slice];
-
+
_readOpCount += 1;
-
+
if (_currentFrameOpcode == SROpCodeTextFrame) {
// Validate UTF8 stuff.
size_t currentDataSize = _currentFrameData.length;
if (_currentFrameOpcode == SROpCodeTextFrame && currentDataSize > 0) {
// TODO: Optimize the crap out of this. Don't really have to copy all the data each time
-
+
size_t scanSize = currentDataSize - _currentStringScanPosition;
-
+
NSData *scan_data = [_currentFrameData subdataWithRange:NSMakeRange(_currentStringScanPosition, scanSize)];
int32_t valid_utf8_size = validate_dispatch_data_partial_string(scan_data);
-
+
if (valid_utf8_size == -1) {
[self closeWithCode:SRStatusCodeInvalidUTF8 reason:@"Text frames must be valid UTF-8"];
dispatch_async(_workQueue, ^{
@@ -1307,12 +1307,12 @@ static const char CRLFCRLFBytes[] = {'\r', '\n', '\r', '\n'};
} else {
_currentStringScanPosition += valid_utf8_size;
}
- }
-
+ }
+
}
-
+
consumer.bytesNeeded -= foundSize;
-
+
if (consumer.bytesNeeded == 0) {
[_consumers removeObjectAtIndex:0];
consumer.handler(self, nil);
@@ -1330,17 +1330,17 @@ static const char CRLFCRLFBytes[] = {'\r', '\n', '\r', '\n'};
-(void)_pumpScanner;
{
[self assertOnWorkQueue];
-
+
if (!_isPumping) {
_isPumping = YES;
} else {
return;
}
-
+
while ([self _innerPumpScanner]) {
-
+
}
-
+
_isPumping = NO;
}
@@ -1351,33 +1351,33 @@ static const size_t SRFrameHeaderOverhead = 32;
- (void)_sendFrameWithOpcode:(FSROpCode)opcode data:(id)data;
{
[self assertOnWorkQueue];
-
+
NSAssert(data == nil || [data isKindOfClass:[NSData class]] || [data isKindOfClass:[NSString class]], @"Function expects nil, NSString or NSData");
-
+
size_t payloadLength = [data isKindOfClass:[NSString class]] ? [(NSString *)data lengthOfBytesUsingEncoding:NSUTF8StringEncoding] : [data length];
-
+
NSMutableData *frame = [[NSMutableData alloc] initWithLength:payloadLength + SRFrameHeaderOverhead];
if (!frame) {
[self closeWithCode:SRStatusCodeMessageTooBig reason:@"Message too big"];
return;
}
uint8_t *frame_buffer = (uint8_t *)[frame mutableBytes];
-
+
// set fin
frame_buffer[0] = SRFinMask | opcode;
-
+
BOOL useMask = YES;
#ifdef NOMASK
useMask = NO;
#endif
-
+
if (useMask) {
// set the mask and header
frame_buffer[1] |= SRMaskMask;
}
-
+
size_t frame_buffer_size = 2;
-
+
const uint8_t *unmasked_payload = NULL;
if ([data isKindOfClass:[NSData class]]) {
unmasked_payload = (uint8_t *)[data bytes];
@@ -1386,7 +1386,7 @@ static const size_t SRFrameHeaderOverhead = 32;
} else {
assert(NO);
}
-
+
if (payloadLength < 126) {
frame_buffer[1] |= payloadLength;
} else if (payloadLength <= UINT16_MAX) {
@@ -1398,7 +1398,7 @@ static const size_t SRFrameHeaderOverhead = 32;
*((uint64_t *)(frame_buffer + frame_buffer_size)) = EndianU64_BtoN((uint64_t)payloadLength);
frame_buffer_size += sizeof(uint64_t);
}
-
+
if (!useMask) {
for (int i = 0; i < payloadLength; i++) {
frame_buffer[frame_buffer_size] = unmasked_payload[i];
@@ -1409,7 +1409,7 @@ static const size_t SRFrameHeaderOverhead = 32;
int result = SecRandomCopyBytes(kSecRandomDefault, sizeof(uint32_t), (uint8_t *)mask_key);
assert(result == 0);
frame_buffer_size += sizeof(uint32_t);
-
+
// TODO: could probably optimize this with SIMD
for (int i = 0; i < payloadLength; i++) {
frame_buffer[frame_buffer_size] = unmasked_payload[i] ^ mask_key[i % sizeof(uint32_t)];
@@ -1419,7 +1419,7 @@ static const size_t SRFrameHeaderOverhead = 32;
assert(frame_buffer_size <= [frame length]);
frame.length = frame_buffer_size;
-
+
[self _writeData:frame];
}
@@ -1445,7 +1445,7 @@ static const size_t SRFrameHeaderOverhead = 32;
}
if (_secure && !_pinnedCertFound && (eventCode == NSStreamEventHasBytesAvailable || eventCode == NSStreamEventHasSpaceAvailable)) {
-
+
NSArray *sslCerts = [_urlRequest FSR_SSLPinnedCertificates];
if (sslCerts) {
SecTrustRef secTrust = (__bridge SecTrustRef)[aStream propertyForKey:(__bridge id)kCFStreamPropertySSLPeerTrust];
@@ -1454,11 +1454,11 @@ static const size_t SRFrameHeaderOverhead = 32;
for (NSInteger i = 0; i < numCerts && !_pinnedCertFound; i++) {
SecCertificateRef cert = SecTrustGetCertificateAtIndex(secTrust, i);
NSData *certData = CFBridgingRelease(SecCertificateCopyData(cert));
-
+
for (id ref in sslCerts) {
SecCertificateRef trustedCert = (__bridge SecCertificateRef)ref;
NSData *trustedCertData = CFBridgingRelease(SecCertificateCopyData(trustedCert));
-
+
if ([trustedCertData isEqualToData:certData]) {
_pinnedCertFound = YES;
break;
@@ -1466,7 +1466,7 @@ static const size_t SRFrameHeaderOverhead = 32;
}
}
}
-
+
if (!_pinnedCertFound) {
dispatch_async(_workQueue, ^{
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : @"Invalid server cert" };
@@ -1669,13 +1669,13 @@ static const size_t SRFrameHeaderOverhead = 32;
- (NSString *)SR_origin;
{
NSString *scheme = [self.scheme lowercaseString];
-
+
if ([scheme isEqualToString:@"wss"]) {
scheme = @"https";
} else if ([scheme isEqualToString:@"ws"]) {
scheme = @"http";
}
-
+
if (self.port) {
return [NSString stringWithFormat:@"%@://%@:%@/", scheme, self.host, self.port];
} else {
@@ -1691,11 +1691,11 @@ static inline void SRFastLog(NSString *format, ...) {
#ifdef SR_ENABLE_LOG
__block va_list arg_list;
va_start (arg_list, format);
-
+
NSString *formattedString = [[NSString alloc] initWithFormat:format arguments:arg_list];
-
+
va_end(arg_list);
-
+
NSLog(@"[SR] %@", formattedString);
#endif
}
@@ -1704,13 +1704,13 @@ static inline void SRFastLog(NSString *format, ...) {
#ifdef HAS_ICU
static inline int32_t validate_dispatch_data_partial_string(NSData *data) {
-
+
const void * contents = [data bytes];
long size = [data length];
-
+
const uint8_t *str = (const uint8_t *)contents;
-
-
+
+
UChar32 codepoint = 1;
int32_t offset = 0;
int32_t lastOffset = 0;
@@ -1718,33 +1718,33 @@ static inline int32_t validate_dispatch_data_partial_string(NSData *data) {
lastOffset = offset;
U8_NEXT(str, offset, size, codepoint);
}
-
+
if (codepoint == -1) {
// Check to see if the last byte is valid or whether it was just continuing
if (!U8_IS_LEAD(str[lastOffset]) || U8_COUNT_TRAIL_BYTES(str[lastOffset]) + lastOffset < (int32_t)size) {
-
+
size = -1;
} else {
uint8_t leadByte = str[lastOffset];
U8_MASK_LEAD_BYTE(leadByte, U8_COUNT_TRAIL_BYTES(leadByte));
-
+
for (int i = lastOffset + 1; i < offset; i++) {
-
+
if (U8_IS_SINGLE(str[i]) || U8_IS_LEAD(str[i]) || !U8_IS_TRAIL(str[i])) {
size = -1;
}
}
-
+
if (size != -1) {
size = lastOffset;
}
}
}
-
+
if (size != -1 && ![[NSString alloc] initWithBytesNoCopy:(char *)[data bytes] length:size encoding:NSUTF8StringEncoding freeWhenDone:NO]) {
size = -1;
}
-
+
return (int32_t)size;
}
@@ -1753,14 +1753,14 @@ static inline int32_t validate_dispatch_data_partial_string(NSData *data) {
// This is a hack, and probably not optimal
static inline int32_t validate_dispatch_data_partial_string(NSData *data) {
static const int maxCodepointSize = 3;
-
+
for (int i = 0; i < maxCodepointSize; i++) {
NSString *str = [[NSString alloc] initWithBytesNoCopy:(char *)data.bytes length:data.length - i encoding:NSUTF8StringEncoding freeWhenDone:NO];
if (str) {
return (int)(data.length - i);
}
}
-
+
return -1;
}