浏览代码

Added OS X framework

Mike Lewis 13 年之前
父节点
当前提交
a856b689dc
共有 3 个文件被更改,包括 153 次插入15 次删除
  1. 5 11
      README.rst
  2. 111 0
      SocketRocket.xcodeproj/project.pbxproj
  3. 37 4
      SocketRocket/SRWebSocket.m

+ 5 - 11
README.rst

@@ -11,20 +11,14 @@ SocketRocket currently conforms to all ~300 of `Autobahn
 <http://www.tavendo.de/autobahn/testsuite.html>`_'s fuzzing tests (aside from
 two UTF-8 ones where it is merely *non-strict*. tests 6.4.2 and 6.4.4)
 
-
-It should work on OS X too.  There are no UIKit dependencies.
-
-.. Warning::
-  This is not production-quality software yet.  It has only been used in
-  devlopment environments.
-  
-  **USE AT YOUR OWN RISK**
-
-  (it will mature quickly… I am just conservative)
+Now has (32-bit only) OS X support.  ``SocketRocket.framework`` inside Xcode
+project is for OS X only.  It should be identical in function aside from the
+unicode validation.  ICU isn't shipped with OS X which is what the original
+implementation used for unicode validation.  The workaround is much more
+rhudimentary and less robust.
 
 Features/Design
 ---------------
-
 - TLS (wss) support.  It uses CFStream so we get this for "free"
 - Uses NSStream/CFNetworking.  Earlier implementations used ``dispatch_io``,
   however, this proved to be make TLS nearly impossible.  Also I wanted this to

+ 111 - 0
SocketRocket.xcodeproj/project.pbxproj

@@ -26,6 +26,14 @@
 		F624180314D53449003CE997 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6A12CD51451231B00C1D980 /* CFNetwork.framework */; };
 		F624180414D53449003CE997 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6A12CD3145122FC00C1D980 /* Security.framework */; };
 		F624180614D53451003CE997 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F6C41C95145F7C4700641356 /* libicucore.dylib */; };
+		F6396B86153E67EC00345B5E /* SRWebSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = F6A12CD0145119B700C1D980 /* SRWebSocket.m */; };
+		F6396B87153E67EC00345B5E /* base64.c in Sources */ = {isa = PBXBuildFile; fileRef = F6016C7B146124B20037BB3D /* base64.c */; };
+		F6396B88153E67EC00345B5E /* NSData+SRB64Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = F6572124146C7B6A00D6B8A9 /* NSData+SRB64Additions.m */; };
+		F6396B8F153E67EC00345B5E /* SRWebSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = F6A12CCF145119B700C1D980 /* SRWebSocket.h */; };
+		F6396B90153E67EC00345B5E /* base64.h in Headers */ = {isa = PBXBuildFile; fileRef = F6016C7E146124ED0037BB3D /* base64.h */; };
+		F6396BA0153E6D3700345B5E /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6396B9F153E6D3700345B5E /* Security.framework */; };
+		F6396BA2153E6D4800345B5E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6396BA1153E6D4800345B5E /* Foundation.framework */; };
+		F6396BA5153E6D7400345B5E /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6396BA4153E6D7400345B5E /* CoreServices.framework */; };
 		F6572126146C7B6A00D6B8A9 /* NSData+SRB64Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = F6572124146C7B6A00D6B8A9 /* NSData+SRB64Additions.m */; };
 		F6A12CD1145119B700C1D980 /* SRWebSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = F6A12CCF145119B700C1D980 /* SRWebSocket.h */; };
 		F6A12CD2145119B700C1D980 /* SRWebSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = F6A12CD0145119B700C1D980 /* SRWebSocket.m */; };
@@ -70,6 +78,10 @@
 		F62417FA14D52F3C003CE997 /* TCViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TCViewController.m; sourceTree = "<group>"; };
 		F62417FF14D5300C003CE997 /* TCChatCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TCChatCell.h; sourceTree = "<group>"; };
 		F624180014D5300C003CE997 /* TCChatCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TCChatCell.m; sourceTree = "<group>"; };
+		F6396B94153E67EC00345B5E /* SocketRocket.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SocketRocket.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		F6396B9F153E6D3700345B5E /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; };
+		F6396BA1153E6D4800345B5E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
+		F6396BA4153E6D7400345B5E /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk/System/Library/Frameworks/CoreServices.framework; sourceTree = DEVELOPER_DIR; };
 		F6572123146C7B6A00D6B8A9 /* NSData+SRB64Additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+SRB64Additions.h"; sourceTree = "<group>"; };
 		F6572124146C7B6A00D6B8A9 /* NSData+SRB64Additions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+SRB64Additions.m"; sourceTree = "<group>"; };
 		F6A12CCF145119B700C1D980 /* SRWebSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SRWebSocket.h; sourceTree = "<group>"; };
@@ -105,6 +117,16 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		F6396B89153E67EC00345B5E /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				F6396BA5153E6D7400345B5E /* CoreServices.framework in Frameworks */,
+				F6396BA2153E6D4800345B5E /* Foundation.framework in Frameworks */,
+				F6396BA0153E6D3700345B5E /* Security.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		F6B2082A1450F597009315AF /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
@@ -158,6 +180,16 @@
 			name = "Supporting Files";
 			sourceTree = "<group>";
 		};
+		F6396BA3153E6D4D00345B5E /* OSX Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				F6396BA4153E6D7400345B5E /* CoreServices.framework */,
+				F6396BA1153E6D4800345B5E /* Foundation.framework */,
+				F6396B9F153E6D3700345B5E /* Security.framework */,
+			);
+			name = "OSX Frameworks";
+			sourceTree = "<group>";
+		};
 		F6B208221450F597009315AF = {
 			isa = PBXGroup;
 			children = (
@@ -177,6 +209,7 @@
 				F6B2082D1450F597009315AF /* libSocketRocket.a */,
 				F6BDA802145900D200FE3253 /* SRWebSocketTests.octest */,
 				F62417E314D52F3C003CE997 /* TestChat.app */,
+				F6396B94153E67EC00345B5E /* SocketRocket.framework */,
 			);
 			name = Products;
 			sourceTree = "<group>";
@@ -184,6 +217,7 @@
 		F6B2082F1450F597009315AF /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
+				F6396BA3153E6D4D00345B5E /* OSX Frameworks */,
 				F6C41C95145F7C4700641356 /* libicucore.dylib */,
 				F6A12CD51451231B00C1D980 /* CFNetwork.framework */,
 				F6A12CD3145122FC00C1D980 /* Security.framework */,
@@ -243,6 +277,15 @@
 /* End PBXGroup section */
 
 /* Begin PBXHeadersBuildPhase section */
+		F6396B8E153E67EC00345B5E /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				F6396B8F153E67EC00345B5E /* SRWebSocket.h in Headers */,
+				F6396B90153E67EC00345B5E /* base64.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		F6B2082B1450F597009315AF /* Headers */ = {
 			isa = PBXHeadersBuildPhase;
 			buildActionMask = 2147483647;
@@ -272,6 +315,23 @@
 			productReference = F62417E314D52F3C003CE997 /* TestChat.app */;
 			productType = "com.apple.product-type.application";
 		};
+		F6396B84153E67EC00345B5E /* SocketRocketOSX */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = F6396B91153E67EC00345B5E /* Build configuration list for PBXNativeTarget "SocketRocketOSX" */;
+			buildPhases = (
+				F6396B85153E67EC00345B5E /* Sources */,
+				F6396B89153E67EC00345B5E /* Frameworks */,
+				F6396B8E153E67EC00345B5E /* Headers */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = SocketRocketOSX;
+			productName = SocketRocket;
+			productReference = F6396B94153E67EC00345B5E /* SocketRocket.framework */;
+			productType = "com.apple.product-type.framework";
+		};
 		F6B2082C1450F597009315AF /* SocketRocket */ = {
 			isa = PBXNativeTarget;
 			buildConfigurationList = F6B2083A1450F597009315AF /* Build configuration list for PBXNativeTarget "SocketRocket" */;
@@ -330,6 +390,7 @@
 			targets = (
 				F6B2082C1450F597009315AF /* SocketRocket */,
 				F6BDA801145900D200FE3253 /* SRWebSocketTests */,
+				F6396B84153E67EC00345B5E /* SocketRocketOSX */,
 				F62417E214D52F3C003CE997 /* TestChat */,
 			);
 		};
@@ -383,6 +444,16 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		F6396B85153E67EC00345B5E /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				F6396B86153E67EC00345B5E /* SRWebSocket.m in Sources */,
+				F6396B87153E67EC00345B5E /* base64.c in Sources */,
+				F6396B88153E67EC00345B5E /* NSData+SRB64Additions.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		F6B208291450F597009315AF /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
@@ -482,6 +553,37 @@
 			};
 			name = Release;
 		};
+		F6396B92153E67EC00345B5E /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+				CLANG_ENABLE_OBJC_ARC = YES;
+				DSTROOT = /tmp/SocketRocket.dst;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = "SocketRocket/SocketRocket-Prefix.pch";
+				ONLY_ACTIVE_ARCH = YES;
+				OTHER_LDFLAGS = "-ObjC";
+				PRODUCT_NAME = SocketRocket;
+				SDKROOT = macosx;
+				SKIP_INSTALL = YES;
+			};
+			name = Debug;
+		};
+		F6396B93153E67EC00345B5E /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+				CLANG_ENABLE_OBJC_ARC = YES;
+				DSTROOT = /tmp/SocketRocket.dst;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = "SocketRocket/SocketRocket-Prefix.pch";
+				OTHER_LDFLAGS = "-ObjC";
+				PRODUCT_NAME = SocketRocket;
+				SDKROOT = macosx;
+				SKIP_INSTALL = YES;
+			};
+			name = Release;
+		};
 		F6B208381450F597009315AF /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
@@ -626,6 +728,15 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
+		F6396B91153E67EC00345B5E /* Build configuration list for PBXNativeTarget "SocketRocketOSX" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				F6396B92153E67EC00345B5E /* Debug */,
+				F6396B93153E67EC00345B5E /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
 		F6B208271450F597009315AF /* Build configuration list for PBXProject "SocketRocket" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (

+ 37 - 4
SocketRocket/SRWebSocket.m

@@ -17,9 +17,22 @@
 
 #import "SRWebSocket.h"
 
+#if TARGET_OS_IPHONE
+#define HAS_ICU
+#endif
+
+#ifdef HAS_ICU
 #import <unicode/utf8.h>
+#endif
+
+#if TARGET_OS_IPHONE
 #import <Endian.h>
+#else
+#import <CoreServices/CoreServices.h>
+#endif
+
 #import <CommonCrypto/CommonDigest.h>
+#import <Security/SecRandom.h>
 #import "base64.h"
 #import "NSData+SRB64Additions.h"
 
@@ -85,13 +98,15 @@ static inline void SRFastLog(NSString *format, ...)  {
 
 static NSString *const SRWebSocketAppendToSecKeyString = @"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
 
+#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;
@@ -109,20 +124,20 @@ static inline int32_t validate_dispatch_data_partial_string(NSData *data) {
         } 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;
     }
@@ -130,6 +145,24 @@ static inline int32_t validate_dispatch_data_partial_string(NSData *data) {
     return size;
 }
 
+#else
+
+// 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 data.length - i;
+        }
+    }
+    
+    return -1;
+}
+
+#endif
+
 
 @interface NSData (SRWebSocket)