From 2c9c4304919334b2b4564bdaa684cd9ab0bec326 Mon Sep 17 00:00:00 2001 From: Jorge Peixoto Vasquez Date: Tue, 3 Mar 2015 18:37:20 -0300 Subject: [PATCH 1/6] Fix compilation warnings --- Core/Mime/MultipartFormDataParser.m | 12 ++++++------ Core/WebSocket.m | 5 ----- Vendor/CocoaAsyncSocket/GCDAsyncSocket.h | 4 ++-- Vendor/CocoaLumberjack/DDTTYLogger.m | 12 ++++++------ 4 files changed, 14 insertions(+), 19 deletions(-) diff --git a/Core/Mime/MultipartFormDataParser.m b/Core/Mime/MultipartFormDataParser.m index 4a19aee5..fd7b3799 100644 --- a/Core/Mime/MultipartFormDataParser.m +++ b/Core/Mime/MultipartFormDataParser.m @@ -29,7 +29,7 @@ + (NSData*) decodedDataFromData:(NSData*) data encoding:(int) encoding; - (int) findHeaderEnd:(NSData*) workingData fromOffset:(int) offset; - (int) findContentEnd:(NSData*) data fromOffset:(int) offset; -- (int) numberOfBytesToLeavePendingWithData:(NSData*) data length:(NSUInteger) length encoding:(int) encoding; +- (NSInteger) numberOfBytesToLeavePendingWithData:(NSData*) data length:(NSInteger) length encoding:(int) encoding; - (int) offsetTillNewlineSinceOffset:(int) offset inData:(NSData*) data; - (int) processPreamble:(NSData*) workingData; @@ -244,10 +244,10 @@ - (BOOL) appendData:(NSData *)data { // this case, we didn't find the boundary, so the data is related to the current part. // we leave the sizeToLeavePending amount of bytes to make sure we don't include // boundary part in processed data. - NSUInteger sizeToPass = workingData.length - offset - sizeToLeavePending; + NSInteger sizeToPass = workingData.length - offset - sizeToLeavePending; // if we parse BASE64 encoded data, or Quoted-Printable data, we will make sure we don't break the format - int leaveTrailing = [self numberOfBytesToLeavePendingWithData:data length:sizeToPass encoding:currentEncoding]; + NSInteger leaveTrailing = [self numberOfBytesToLeavePendingWithData:data length:sizeToPass encoding:currentEncoding]; sizeToPass -= leaveTrailing; if( sizeToPass <= 0 ) { @@ -417,14 +417,14 @@ - (int) findContentEnd:(NSData*) data fromOffset:(int) offset { } -- (int) numberOfBytesToLeavePendingWithData:(NSData*) data length:(int) length encoding:(int) encoding { +- (NSInteger) numberOfBytesToLeavePendingWithData:(NSData*) data length:(NSInteger) length encoding:(int) encoding { // If we have BASE64 or Quoted-Printable encoded data, we have to be sure // we don't break the format. - int sizeToLeavePending = 0; + NSInteger sizeToLeavePending = 0; if( encoding == contentTransferEncoding_base64 ) { char* bytes = (char*) data.bytes; - int i; + NSInteger i; for( i = length - 1; i > 0; i++ ) { if( * (uint16_t*) (bytes + i) == 0x0A0D ) { break; diff --git a/Core/WebSocket.m b/Core/WebSocket.m index 9051ac3e..9b7eb47e 100644 --- a/Core/WebSocket.m +++ b/Core/WebSocket.m @@ -36,11 +36,6 @@ #define WS_OP_PING 9 #define WS_OP_PONG 10 -static inline BOOL WS_OP_IS_FINAL_FRAGMENT(UInt8 frame) -{ - return (frame & 0x80) ? YES : NO; -} - static inline BOOL WS_PAYLOAD_IS_MASKED(UInt8 frame) { return (frame & 0x80) ? YES : NO; diff --git a/Vendor/CocoaAsyncSocket/GCDAsyncSocket.h b/Vendor/CocoaAsyncSocket/GCDAsyncSocket.h index cf9927f7..40686fe7 100644 --- a/Vendor/CocoaAsyncSocket/GCDAsyncSocket.h +++ b/Vendor/CocoaAsyncSocket/GCDAsyncSocket.h @@ -54,8 +54,8 @@ // Compiling for Mac OS X #define IS_SECURE_TRANSPORT_AVAILABLE YES - #define SECURE_TRANSPORT_MAYBE_AVAILABLE 1 - #define SECURE_TRANSPORT_MAYBE_UNAVAILABLE 0 + #define SECURE_TRANSPORT_MAYBE_AVAILABLE 0 + #define SECURE_TRANSPORT_MAYBE_UNAVAILABLE 1 #endif diff --git a/Vendor/CocoaLumberjack/DDTTYLogger.m b/Vendor/CocoaLumberjack/DDTTYLogger.m index 2906463c..4ddb7913 100755 --- a/Vendor/CocoaLumberjack/DDTTYLogger.m +++ b/Vendor/CocoaLumberjack/DDTTYLogger.m @@ -822,12 +822,12 @@ - (id)init calendar = [NSCalendar autoupdatingCurrentCalendar]; calendarUnitFlags = 0; - calendarUnitFlags |= NSYearCalendarUnit; - calendarUnitFlags |= NSMonthCalendarUnit; - calendarUnitFlags |= NSDayCalendarUnit; - calendarUnitFlags |= NSHourCalendarUnit; - calendarUnitFlags |= NSMinuteCalendarUnit; - calendarUnitFlags |= NSSecondCalendarUnit; + calendarUnitFlags |= NSCalendarUnitYear; + calendarUnitFlags |= NSCalendarUnitMonth; + calendarUnitFlags |= NSCalendarUnitDay; + calendarUnitFlags |= NSCalendarUnitHour; + calendarUnitFlags |= NSCalendarUnitMinute; + calendarUnitFlags |= NSCalendarUnitSecond; // Initialze 'app' variable (char *) From f91aa6dbfb7d86085c8236c591964a4a82228454 Mon Sep 17 00:00:00 2001 From: Jorge Peixoto Vasquez Date: Tue, 3 Mar 2015 19:13:15 -0300 Subject: [PATCH 2/6] Supports binary data --- Core/WebSocket.h | 3 +++ Core/WebSocket.m | 38 +++++++++++++++++++++++++++++++++----- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/Core/WebSocket.h b/Core/WebSocket.h index 4ee51371..9a43c98b 100644 --- a/Core/WebSocket.h +++ b/Core/WebSocket.h @@ -73,6 +73,7 @@ **/ - (void)didOpen; - (void)didReceiveMessage:(NSString *)msg; +- (void)didReceiveData:(NSData *)data; - (void)didClose; @end @@ -102,4 +103,6 @@ - (void)webSocketDidClose:(WebSocket *)ws; +- (void)webSocket:(WebSocket *)ws didReceiveData:(NSData *)data; + @end diff --git a/Core/WebSocket.m b/Core/WebSocket.m index 9b7eb47e..d106101e 100644 --- a/Core/WebSocket.m +++ b/Core/WebSocket.m @@ -597,6 +597,22 @@ - (void)didReceiveMessage:(NSString *)msg } } +- (void)didReceiveData:(NSData *)data +{ + HTTPLogTrace(); + + // Override me to process incoming data. + // This method is invoked on the websocketQueue. + // + // For completeness, you should invoke [super didReceiveData:data] in your method. + + // Notify delegate + if ([delegate respondsToSelector:@selector(webSocket:didReceiveData:)]) + { + [delegate webSocket:self didReceiveData:data]; + } +} + - (void)didClose { HTTPLogTrace(); @@ -749,6 +765,10 @@ - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)t NSString *msg = [[NSString alloc] initWithBytes:[data bytes] length:msgLength encoding:NSUTF8StringEncoding]; [self didReceiveMessage:msg]; } + else if (nextOpCode == WS_OP_BINARY_FRAME) + { + [self didReceiveData:data]; + } else { [self didClose]; @@ -765,11 +785,19 @@ - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)t else { NSUInteger msgLength = [data length] - 1; // Excluding ending 0xFF frame - - NSString *msg = [[NSString alloc] initWithBytes:[data bytes] length:msgLength encoding:NSUTF8StringEncoding]; - - [self didReceiveMessage:msg]; - + + if (nextOpCode == WS_OP_TEXT_FRAME) + { + NSString *msg = [[NSString alloc] initWithBytes:[data bytes] length:msgLength encoding:NSUTF8StringEncoding]; + + [self didReceiveMessage:msg]; + } + else if(nextOpCode == WS_OP_BINARY_FRAME) + { + NSData *msg = [data subdataWithRange:NSMakeRange(0, msgLength)]; + + [self didReceiveData:msg]; + } // Read next message [asyncSocket readDataToLength:1 withTimeout:TIMEOUT_NONE tag:TAG_PREFIX]; From f45809cb19f35af0639a986f564cd56eeea4f732 Mon Sep 17 00:00:00 2001 From: Jorge Peixoto Vasquez Date: Fri, 6 Mar 2015 19:08:52 -0300 Subject: [PATCH 3/6] Fixes bug where it would not work on Mac without SECURE_TRANSPORT_MAYBE_AVAILABLE --- Vendor/CocoaAsyncSocket/GCDAsyncSocket.m | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Vendor/CocoaAsyncSocket/GCDAsyncSocket.m b/Vendor/CocoaAsyncSocket/GCDAsyncSocket.m index 1ecc94af..accb066e 100644 --- a/Vendor/CocoaAsyncSocket/GCDAsyncSocket.m +++ b/Vendor/CocoaAsyncSocket/GCDAsyncSocket.m @@ -4263,10 +4263,9 @@ - (void)doReadData } else { - #if SECURE_TRANSPORT_MAYBE_AVAILABLE - estimatedBytesAvailable = socketFDBytesAvailable; +#if SECURE_TRANSPORT_MAYBE_AVAILABLE if (flags & kSocketSecure) { // There are 2 buffers to be aware of here. @@ -4303,9 +4302,9 @@ - (void)doReadData estimatedBytesAvailable += sslInternalBufSize; } +#endif hasBytesAvailable = (estimatedBytesAvailable > 0); - #endif } if ((hasBytesAvailable == NO) && ([preBuffer availableBytes] == 0)) From 5ade0b83d7ff7581d58c09003b095ef876b3fd1f Mon Sep 17 00:00:00 2001 From: Jorge Peixoto Vasquez Date: Fri, 6 Mar 2015 19:09:08 -0300 Subject: [PATCH 4/6] Allows sending of binary and textual data --- Core/WebSocket.h | 4 ++-- Core/WebSocket.m | 17 ++++++++++++----- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Core/WebSocket.h b/Core/WebSocket.h index 9a43c98b..e43b5fc1 100644 --- a/Core/WebSocket.h +++ b/Core/WebSocket.h @@ -24,7 +24,7 @@ + (BOOL)isWebSocketRequest:(HTTPMessage *)request; -- (id)initWithRequest:(HTTPMessage *)request socket:(GCDAsyncSocket *)socket; +- (id)initWithRequest:(HTTPMessage *)request socket:(GCDAsyncSocket *)socket NS_DESIGNATED_INITIALIZER; /** * Delegate option. @@ -64,7 +64,7 @@ * Sends a message over the WebSocket. * This method is thread-safe. **/ -- (void)sendData:(NSData *)msg; +- (void)sendData:(NSData *)msg isBinary:(BOOL)binary; /** * Subclass API diff --git a/Core/WebSocket.m b/Core/WebSocket.m index d106101e..c0bc39bb 100644 --- a/Core/WebSocket.m +++ b/Core/WebSocket.m @@ -531,10 +531,10 @@ - (void)didOpen - (void)sendMessage:(NSString *)msg { NSData *msgData = [msg dataUsingEncoding:NSUTF8StringEncoding]; - [self sendData:msgData]; + [self sendData:msgData isBinary:NO]; } -- (void)sendData:(NSData *)msgData +- (void)sendData:(NSData *)msgData isBinary:(BOOL)binary { HTTPLogTrace(); @@ -543,10 +543,17 @@ - (void)sendData:(NSData *)msgData if (isRFC6455) { NSUInteger length = msgData.length; + UInt8 firstByte = 0x80; + if(binary) + firstByte |= WS_OP_BINARY_FRAME; + else + firstByte |= WS_OP_TEXT_FRAME; + if (length <= 125) { data = [NSMutableData dataWithCapacity:(length + 2)]; - [data appendBytes: "\x81" length:1]; + + [data appendBytes: &firstByte length:1]; UInt8 len = (UInt8)length; [data appendBytes: &len length:1]; [data appendData:msgData]; @@ -554,7 +561,7 @@ - (void)sendData:(NSData *)msgData else if (length <= 0xFFFF) { data = [NSMutableData dataWithCapacity:(length + 4)]; - [data appendBytes: "\x81\x7E" length:2]; + [data appendBytes: (UInt8[]){firstByte, 0x7e} length:2]; UInt16 len = (UInt16)length; [data appendBytes: (UInt8[]){len >> 8, len & 0xFF} length:2]; [data appendData:msgData]; @@ -562,7 +569,7 @@ - (void)sendData:(NSData *)msgData else { data = [NSMutableData dataWithCapacity:(length + 10)]; - [data appendBytes: "\x81\x7F" length:2]; + [data appendBytes: (UInt8[]){firstByte, 0x7f} length:2]; [data appendBytes: (UInt8[]){0, 0, 0, 0, (UInt8)(length >> 24), (UInt8)(length >> 16), (UInt8)(length >> 8), length & 0xFF} length:8]; [data appendData:msgData]; } From 2861937527e7ba062d181227d42f93b8384a76b6 Mon Sep 17 00:00:00 2001 From: Jorge Peixoto Vasquez Date: Thu, 10 Sep 2015 15:56:46 -0300 Subject: [PATCH 5/6] Fix designated initializer warning --- Core/WebSocket.m | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Core/WebSocket.m b/Core/WebSocket.m index c0bc39bb..9256b9a6 100644 --- a/Core/WebSocket.m +++ b/Core/WebSocket.m @@ -150,6 +150,12 @@ + (BOOL)isRFC6455Request:(HTTPMessage *)request @synthesize websocketQueue; +- (instancetype)init +{ + [NSException raise:NSInternalInconsistencyException format:@"Initializer disallowed: %s", __PRETTY_FUNCTION__]; + return [self initWithRequest:nil socket:nil]; +} + - (id)initWithRequest:(HTTPMessage *)aRequest socket:(GCDAsyncSocket *)socket { HTTPLogTrace(); From 3f769cb8b45a0724278daceb80e872f7b981009a Mon Sep 17 00:00:00 2001 From: Jorge Peixoto Vasquez Date: Mon, 3 Apr 2017 23:54:51 -0700 Subject: [PATCH 6/6] Static analyzer fixes --- Core/Mime/MultipartMessageHeaderField.m | 3 ++- Core/WebSocket.m | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Core/Mime/MultipartMessageHeaderField.m b/Core/Mime/MultipartMessageHeaderField.m index 00ecac84..036ddf21 100644 --- a/Core/Mime/MultipartMessageHeaderField.m +++ b/Core/Mime/MultipartMessageHeaderField.m @@ -163,7 +163,8 @@ -(BOOL) parseHeaderValueBytes:(char*) bytes length:(NSUInteger) length encoding: HTTPLogWarn(@"MultipartFormDataParser: param %@ mentioned more then once in one header",currentParam); } #endif - [params setObject:paramValue forKey:currentParam]; + if(paramValue != nil) + [params setObject:paramValue forKey:currentParam]; HTTPLogVerbose(@"MultipartFormDataParser: header param: %@ = %@",currentParam,paramValue); currentParam = nil; } diff --git a/Core/WebSocket.m b/Core/WebSocket.m index 9256b9a6..88c53ac1 100644 --- a/Core/WebSocket.m +++ b/Core/WebSocket.m @@ -103,7 +103,7 @@ + (BOOL)isWebSocketRequest:(HTTPMessage *)request if (!upgradeHeaderValue || !connectionHeaderValue) { isWebSocket = NO; } - else if (![upgradeHeaderValue caseInsensitiveCompare:@"WebSocket"] == NSOrderedSame) { + else if ([upgradeHeaderValue caseInsensitiveCompare:@"WebSocket"] != NSOrderedSame) { isWebSocket = NO; } else if ([connectionHeaderValue rangeOfString:@"Upgrade" options:NSCaseInsensitiveSearch].location == NSNotFound) {