瀏覽代碼

Merging upstream

Jorge Leandro Perez 9 年之前
父節點
當前提交
2c95c1364d

+ 1 - 0
.travis.yml

@@ -4,5 +4,6 @@ before_script:
     - bundle install
 script:
     - xcodebuild -project SocketRocket.xcodeproj -scheme "SocketRocket" -sdk iphonesimulator -configuration Debug -PBXBuildsContinueAfterErrors=0 ACTIVE_ARCH_ONLY=0 build test
+    - xcodebuild -project SocketRocket.xcodeproj -scheme "SocketRocket-iOS" -sdk iphonesimulator -configuration Debug -PBXBuildsContinueAfterErrors=0 ACTIVE_ARCH_ONLY=0 build
     - xcodebuild -project SocketRocket.xcodeproj -scheme "SocketRocketOSX" -sdk macosx10.10 -configuration Debug -destination "platform=OS X" -PBXBuildsContinueAfterErrors=0 build
     - pod lib lint --verbose --fail-fast

+ 6 - 0
Makefile

@@ -1,6 +1,12 @@
 TEST_SCENARIOS="[1-8]*"
 TEST_URL='ws://localhost:9001/'
 
+all:
+	$(MAKE) -C SocketRocket
+
+clean:
+	$(MAKE) -C SocketRocket clean
+
 test:
 
 	mkdir -p pages/results

+ 1 - 1
README.rst

@@ -8,7 +8,7 @@ You can compare to what `modern browsers look like here
 <http://www.tavendo.de/autobahn/testsuite/report/clients/index.html>`_.
 
 SocketRocket currently conforms to all ~300 of `Autobahn
-<http://www.tavendo.de/autobahn/testsuite.html>`_'s fuzzing tests (aside from
+<http://autobahn.ws/testsuite/>`_'s fuzzing tests (aside from
 two UTF-8 ones where it is merely *non-strict*. tests 6.4.2 and 6.4.4)
 
 Features/Design

+ 1 - 1
SRWebSocketTests/SRTAutobahnTests.m

@@ -16,7 +16,7 @@
 
 #import <XCTest/XCTest.h>
 #import <XCTest/XCTestRun.h>
-#import "SRWebSocket.h"
+#import <SocketRocket/SRWebSocket.h>
 #import "SRTWebSocketOperation.h"
 #import "SenTestCase+SRTAdditions.h"
 

+ 1 - 1
SRWebSocketTests/SRTWebSocketOperation.h

@@ -8,7 +8,7 @@
 
 #import <Foundation/Foundation.h>
 
-#import "SRWebSocket.h"
+#import <SocketRocket/SRWebSocket.h>
 
 @interface SRTWebSocketOperation : NSOperation <SRWebSocketDelegate>
 

+ 0 - 1
SRWebSocketTests/SRTWebSocketOperation.m

@@ -7,7 +7,6 @@
 //
 
 #import "SRTWebSocketOperation.h"
-#import "SRWebSocket.h"
 
 @interface SRTWebSocketOperation ()
 

+ 26 - 0
SocketRocket-iOS/SocketRocket-iOS-Info.plist

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>FMWK</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>$(CURRENT_PROJECT_VERSION)</string>
+	<key>NSPrincipalClass</key>
+	<string></string>
+</dict>
+</plist>

+ 18 - 0
SocketRocket-iOS/SocketRocket.h

@@ -0,0 +1,18 @@
+//
+//   Copyright 2012 - 2015 Square Inc.
+//
+//   Licensed under the Apache License, Version 2.0 (the "License");
+//   you may not use this file except in compliance with the License.
+//   You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+//   Unless required by applicable law or agreed to in writing, software
+//   distributed under the License is distributed on an "AS IS" BASIS,
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//   See the License for the specific language governing permissions and
+//   limitations under the License.
+//
+
+#import <Foundation/Foundation.h>
+#import <SocketRocket/SRWebSocket.h>

+ 1 - 1
SocketRocket.podspec

@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name               = "SocketRocket"
-  s.version            = '0.4.1'
+  s.version            = '0.4.2'
   s.summary            = 'A conforming WebSocket (RFC 6455) client library.'
   s.homepage           = 'https://github.com/square/SocketRocket'
   s.authors            = 'Square'

+ 155 - 0
SocketRocket.xcodeproj/project.pbxproj

@@ -7,6 +7,12 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		2D42277F1BB4365C000C1A6C /* SRWebSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = F6A12CCF145119B700C1D980 /* SRWebSocket.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		2D4227801BB43693000C1A6C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6B208301450F597009315AF /* Foundation.framework */; };
+		2D4227831BB436B1000C1A6C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6A12CD3145122FC00C1D980 /* Security.framework */; };
+		2D4227841BB436CF000C1A6C /* SocketRocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D4227641BB4358C000C1A6C /* SocketRocket.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		2D4227851BB43734000C1A6C /* SRWebSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = F6A12CD0145119B700C1D980 /* SRWebSocket.m */; };
+		2D8650261BB43B9B00534598 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F6C41C95145F7C4700641356 /* libicucore.dylib */; };
 		F6016C8814620EC70037BB3D /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6A12CD3145122FC00C1D980 /* Security.framework */; };
 		F6016C8914620ECC0037BB3D /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6A12CD3145122FC00C1D980 /* Security.framework */; };
 		F6016C8A1462143C0037BB3D /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6A12CD51451231B00C1D980 /* CFNetwork.framework */; };
@@ -53,6 +59,9 @@
 /* End PBXContainerItemProxy section */
 
 /* Begin PBXFileReference section */
+		2D4227621BB4358C000C1A6C /* SocketRocket.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SocketRocket.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		2D4227641BB4358C000C1A6C /* SocketRocket.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SocketRocket.h; sourceTree = "<group>"; };
+		2D4227661BB4358C000C1A6C /* SocketRocket-iOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SocketRocket-iOS-Info.plist"; sourceTree = "<group>"; };
 		F60CC29F14D4EA0500A005E4 /* SRTWebSocketOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SRTWebSocketOperation.h; sourceTree = "<group>"; };
 		F60CC2A014D4EA0500A005E4 /* SRTWebSocketOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SRTWebSocketOperation.m; sourceTree = "<group>"; };
 		F61A0DC71625F44D00365EBD /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default-568h@2x.png"; path = "en.lproj/Default-568h@2x.png"; sourceTree = "<group>"; };
@@ -96,6 +105,16 @@
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
+		2D42275E1BB4358C000C1A6C /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				2D8650261BB43B9B00534598 /* libicucore.dylib in Frameworks */,
+				2D4227831BB436B1000C1A6C /* Security.framework in Frameworks */,
+				2D4227801BB43693000C1A6C /* Foundation.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		F62417E014D52F3C003CE997 /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
@@ -145,6 +164,15 @@
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
+		2D4227631BB4358C000C1A6C /* SocketRocket-iOS */ = {
+			isa = PBXGroup;
+			children = (
+				2D4227641BB4358C000C1A6C /* SocketRocket.h */,
+				2D4227661BB4358C000C1A6C /* SocketRocket-iOS-Info.plist */,
+			);
+			path = "SocketRocket-iOS";
+			sourceTree = "<group>";
+		};
 		F62417EA14D52F3C003CE997 /* TestChat */ = {
 			isa = PBXGroup;
 			children = (
@@ -207,6 +235,7 @@
 				F6BDA807145900D200FE3253 /* SRWebSocketTests */,
 				F62417EA14D52F3C003CE997 /* TestChat */,
 				F668C887153E91210044DBAC /* SocketRocketOSX */,
+				2D4227631BB4358C000C1A6C /* SocketRocket-iOS */,
 				F6B2082F1450F597009315AF /* Frameworks */,
 				F6B2082E1450F597009315AF /* Products */,
 			);
@@ -221,6 +250,7 @@
 				F6BDA802145900D200FE3253 /* SRWebSocketTests.xctest */,
 				F62417E314D52F3C003CE997 /* TestChat.app */,
 				F668C880153E91210044DBAC /* SocketRocket.framework */,
+				2D4227621BB4358C000C1A6C /* SocketRocket.framework */,
 			);
 			name = Products;
 			sourceTree = "<group>";
@@ -284,6 +314,15 @@
 /* End PBXGroup section */
 
 /* Begin PBXHeadersBuildPhase section */
+		2D42275F1BB4358C000C1A6C /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				2D42277F1BB4365C000C1A6C /* SRWebSocket.h in Headers */,
+				2D4227841BB436CF000C1A6C /* SocketRocket.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		F668C87D153E91210044DBAC /* Headers */ = {
 			isa = PBXHeadersBuildPhase;
 			buildActionMask = 2147483647;
@@ -303,6 +342,24 @@
 /* End PBXHeadersBuildPhase section */
 
 /* Begin PBXNativeTarget section */
+		2D4227611BB4358C000C1A6C /* SocketRocket-iOS */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 2D4227671BB4358C000C1A6C /* Build configuration list for PBXNativeTarget "SocketRocket-iOS" */;
+			buildPhases = (
+				2D42275D1BB4358C000C1A6C /* Sources */,
+				2D42275E1BB4358C000C1A6C /* Frameworks */,
+				2D42275F1BB4358C000C1A6C /* Headers */,
+				2D4227601BB4358C000C1A6C /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "SocketRocket-iOS";
+			productName = "SocketRocket-iOS";
+			productReference = 2D4227621BB4358C000C1A6C /* SocketRocket.framework */;
+			productType = "com.apple.product-type.framework";
+		};
 		F62417E214D52F3C003CE997 /* TestChat */ = {
 			isa = PBXNativeTarget;
 			buildConfigurationList = F62417FC14D52F3C003CE997 /* Build configuration list for PBXNativeTarget "TestChat" */;
@@ -396,6 +453,7 @@
 			targets = (
 				F6B2082C1450F597009315AF /* SocketRocket */,
 				F668C87F153E91210044DBAC /* SocketRocketOSX */,
+				2D4227611BB4358C000C1A6C /* SocketRocket-iOS */,
 				F6BDA801145900D200FE3253 /* SRWebSocketTests */,
 				F62417E214D52F3C003CE997 /* TestChat */,
 			);
@@ -403,6 +461,13 @@
 /* End PBXProject section */
 
 /* Begin PBXResourcesBuildPhase section */
+		2D4227601BB4358C000C1A6C /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		F62417E114D52F3C003CE997 /* Resources */ = {
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
@@ -431,6 +496,14 @@
 /* End PBXResourcesBuildPhase section */
 
 /* Begin PBXSourcesBuildPhase section */
+		2D42275D1BB4358C000C1A6C /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				2D4227851BB43734000C1A6C /* SRWebSocket.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		F62417DF14D52F3C003CE997 /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
@@ -506,6 +579,77 @@
 /* End PBXVariantGroup section */
 
 /* Begin XCBuildConfiguration section */
+		2D4227681BB4358C000C1A6C /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				CURRENT_PROJECT_VERSION = 1;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				DEFINES_MODULE = YES;
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				DYLIB_INSTALL_NAME_BASE = "@rpath";
+				ENABLE_TESTABILITY = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				INFOPLIST_FILE = "SocketRocket-iOS/SocketRocket-iOS-Info.plist";
+				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				MTL_ENABLE_DEBUG_INFO = YES;
+				OTHER_LDFLAGS = "-ObjC";
+				PRODUCT_BUNDLE_IDENTIFIER = com.squareup.SocketRocket;
+				PRODUCT_NAME = SocketRocket;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				VERSIONING_SYSTEM = "apple-generic";
+				VERSION_INFO_PREFIX = "";
+			};
+			name = Debug;
+		};
+		2D4227691BB4358C000C1A6C /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = NO;
+				CURRENT_PROJECT_VERSION = 1;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				DEFINES_MODULE = YES;
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				DYLIB_INSTALL_NAME_BASE = "@rpath";
+				ENABLE_NS_ASSERTIONS = NO;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				INFOPLIST_FILE = "SocketRocket-iOS/SocketRocket-iOS-Info.plist";
+				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				MTL_ENABLE_DEBUG_INFO = NO;
+				OTHER_LDFLAGS = "-ObjC";
+				PRODUCT_BUNDLE_IDENTIFIER = com.squareup.SocketRocket;
+				PRODUCT_NAME = SocketRocket;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				VERSIONING_SYSTEM = "apple-generic";
+				VERSION_INFO_PREFIX = "";
+			};
+			name = Release;
+		};
 		F62417FD14D52F3C003CE997 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
@@ -690,6 +834,7 @@
 				);
 				OTHER_LDFLAGS = "-Licucore";
 				PRODUCT_NAME = "$(TARGET_NAME)";
+				PUBLIC_HEADERS_FOLDER_PATH = include/$PRODUCT_NAME;
 				SKIP_INSTALL = YES;
 			};
 			name = Debug;
@@ -708,6 +853,7 @@
 				);
 				OTHER_LDFLAGS = "-Licucore";
 				PRODUCT_NAME = "$(TARGET_NAME)";
+				PUBLIC_HEADERS_FOLDER_PATH = include/$PRODUCT_NAME;
 				SKIP_INSTALL = YES;
 			};
 			name = Release;
@@ -755,6 +901,15 @@
 /* End XCBuildConfiguration section */
 
 /* Begin XCConfigurationList section */
+		2D4227671BB4358C000C1A6C /* Build configuration list for PBXNativeTarget "SocketRocket-iOS" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				2D4227681BB4358C000C1A6C /* Debug */,
+				2D4227691BB4358C000C1A6C /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
 		F62417FC14D52F3C003CE997 /* Build configuration list for PBXNativeTarget "TestChat" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (

+ 80 - 0
SocketRocket.xcodeproj/xcshareddata/xcschemes/SocketRocket-iOS.xcscheme

@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0700"
+   version = "1.8">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "2D4227611BB4358C000C1A6C"
+               BuildableName = "SocketRocket.framework"
+               BlueprintName = "SocketRocket-iOS"
+               ReferencedContainer = "container:SocketRocket.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <Testables>
+      </Testables>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      buildConfiguration = "Debug"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "2D4227611BB4358C000C1A6C"
+            BuildableName = "SocketRocket.framework"
+            BlueprintName = "SocketRocket-iOS"
+            ReferencedContainer = "container:SocketRocket.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      buildConfiguration = "Release"
+      debugDocumentVersioning = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "2D4227611BB4358C000C1A6C"
+            BuildableName = "SocketRocket.framework"
+            BlueprintName = "SocketRocket-iOS"
+            ReferencedContainer = "container:SocketRocket.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 20 - 0
SocketRocket/Makefile

@@ -0,0 +1,20 @@
+BINS := SocketRocket.framework libSocketRocket.a
+
+all: $(BINS)
+
+HEADERS := SRWebSocket.h
+SRCS := SRWebSocket.m
+OBJS := $(SRCS:%.m=%.o)
+
+CFLAGS += -fobjc-arc
+
+libSocketRocket.a: $(OBJS)
+	$(AR) -rc $(AFLAGS) $@ $^
+
+SocketRocket.framework: libSocketRocket.a
+	mkdir -p $@/Headers
+	cp -f $(HEADERS) $@/Headers
+	cp $^ $@/SocketRocket
+
+clean:
+	rm -r $(OBJS) $(BINS)

+ 7 - 4
SocketRocket/SRWebSocket.h

@@ -55,6 +55,7 @@ extern NSString *const SRHTTPResponseErrorKey;
 @property (nonatomic, readonly) SRReadyState readyState;
 @property (nonatomic, readonly, retain) NSURL *url;
 
+
 @property (nonatomic, readonly) CFHTTPMessageRef receivedHTTPHeaders;
 
 // Optional array of cookies (NSHTTPCookie objects) to apply to the connections
@@ -65,10 +66,12 @@ extern NSString *const SRHTTPResponseErrorKey;
 @property (nonatomic, readonly, copy) NSString *protocol;
 
 // Protocols should be an array of strings that turn into Sec-WebSocket-Protocol.
+- (id)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols allowsUntrustedSSLCertificates:(BOOL)allowsUntrustedSSLCertificates;
 - (id)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols;
 - (id)initWithURLRequest:(NSURLRequest *)request;
 
 // Some helper constructors.
+- (id)initWithURL:(NSURL *)url protocols:(NSArray *)protocols allowsUntrustedSSLCertificates:(BOOL)allowsUntrustedSSLCertificates;
 - (id)initWithURL:(NSURL *)url protocols:(NSArray *)protocols;
 - (id)initWithURL:(NSURL *)url;
 
@@ -112,17 +115,17 @@ extern NSString *const SRHTTPResponseErrorKey;
 
 @end
 
-#pragma mark - NSURLRequest (CertificateAdditions)
+#pragma mark - NSURLRequest (SRCertificateAdditions)
 
-@interface NSURLRequest (CertificateAdditions)
+@interface NSURLRequest (SRCertificateAdditions)
 
 @property (nonatomic, retain, readonly) NSArray *SR_SSLPinnedCertificates;
 
 @end
 
-#pragma mark - NSMutableURLRequest (CertificateAdditions)
+#pragma mark - NSMutableURLRequest (SRCertificateAdditions)
 
-@interface NSMutableURLRequest (CertificateAdditions)
+@interface NSMutableURLRequest (SRCertificateAdditions)
 
 @property (nonatomic, retain) NSArray *SR_SSLPinnedCertificates;
 

+ 106 - 15
SocketRocket/SRWebSocket.m

@@ -183,6 +183,12 @@ typedef void (^data_callback)(SRWebSocket *webSocket,  NSData *data);
 @property (nonatomic) NSOperationQueue *delegateOperationQueue;
 @property (nonatomic) dispatch_queue_t delegateDispatchQueue;
 
+// Specifies whether SSL trust chain should NOT be evaluated.
+// By default this flag is set to NO, meaning only secure SSL connections are allowed.
+// For DEBUG builds this flag is ignored, and SSL connections are allowed regardless
+// of the certificate trust configuration
+@property (nonatomic, readwrite) BOOL allowsUntrustedSSLCertificates;
+
 @end
 
 
@@ -213,6 +219,7 @@ typedef void (^data_callback)(SRWebSocket *webSocket,  NSData *data);
     NSString *_closeReason;
     
     NSString *_secKey;
+    NSString *_basicAuthorizationString;
     
     BOOL _pinnedCertFound;
     
@@ -227,8 +234,6 @@ typedef void (^data_callback)(SRWebSocket *webSocket,  NSData *data);
     BOOL _secure;
     NSURLRequest *_urlRequest;
 
-    
-    
     BOOL _sentClose;
     BOOL _didFail;
     BOOL _cleanupScheduled;
@@ -257,13 +262,14 @@ static __strong NSData *CRLFCRLF;
     CRLFCRLF = [[NSData alloc] initWithBytes:"\r\n\r\n" length:4];
 }
 
-- (id)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols;
+- (id)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols allowsUntrustedSSLCertificates:(BOOL)allowsUntrustedSSLCertificates;
 {
     self = [super init];
     if (self) {
         assert(request.URL);
         _url = request.URL;
         _urlRequest = request;
+        _allowsUntrustedSSLCertificates = allowsUntrustedSSLCertificates;
         
         _requestedProtocols = [protocols copy];
         
@@ -273,6 +279,11 @@ static __strong NSData *CRLFCRLF;
     return self;
 }
 
+- (id)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols;
+{
+    return [self initWithURLRequest:request protocols:protocols allowsUntrustedSSLCertificates:NO];
+}
+
 - (id)initWithURLRequest:(NSURLRequest *)request;
 {
     return [self initWithURLRequest:request protocols:nil];
@@ -289,9 +300,14 @@ static __strong NSData *CRLFCRLF;
     return [self initWithURLRequest:request protocols:protocols];
 }
 
+- (id)initWithURL:(NSURL *)url protocols:(NSArray *)protocols allowsUntrustedSSLCertificates:(BOOL)allowsUntrustedSSLCertificates;
+{
+    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
+    return [self initWithURLRequest:request protocols:protocols allowsUntrustedSSLCertificates:allowsUntrustedSSLCertificates];
+}
+
 - (void)_SR_commonInit;
 {
-    
     NSString *scheme = _url.scheme.lowercaseString;
     assert([scheme isEqualToString:@"ws"] || [scheme isEqualToString:@"http"] || [scheme isEqualToString:@"wss"] || [scheme isEqualToString:@"https"]);
     
@@ -474,7 +490,7 @@ static __strong NSData *CRLFCRLF;
     }];
 }
 
-- (void)didConnect
+- (void)didConnect;
 {
     SRFastLog(@"Connected");
     CFHTTPMessageRef request = CFHTTPMessageCreateRequest(NULL, CFSTR("GET"), (__bridge CFURLRef)_url, kCFHTTPVersion1_1);
@@ -505,6 +521,22 @@ static __strong NSData *CRLFCRLF;
         }
     }
  
+    // set header for http basic auth
+    if (_url.user.length && _url.password.length) {
+        NSData *userAndPassword = [[NSString stringWithFormat:@"%@:%@", _url.user, _url.password] dataUsingEncoding:NSUTF8StringEncoding];
+        NSString *userAndPasswordBase64Encoded;
+        if ([keyBytes respondsToSelector:@selector(base64EncodedStringWithOptions:)]) {
+            userAndPasswordBase64Encoded = [userAndPassword base64EncodedStringWithOptions:0];
+        } else {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+            userAndPasswordBase64Encoded = [userAndPassword base64Encoding];
+#pragma clang diagnostic pop
+        }
+        _basicAuthorizationString = [NSString stringWithFormat:@"Basic %@", userAndPasswordBase64Encoded];
+        CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Authorization"), (__bridge CFStringRef)_basicAuthorizationString);
+    }
+
     CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Upgrade"), CFSTR("websocket"));
     CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Connection"), CFSTR("Upgrade"));
     CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Sec-WebSocket-Key"), (__bridge CFStringRef)_secKey);
@@ -549,7 +581,12 @@ static __strong NSData *CRLFCRLF;
     _outputStream = CFBridgingRelease(writeStream);
     _inputStream = CFBridgingRelease(readStream);
     
-    
+    _inputStream.delegate = self;
+    _outputStream.delegate = self;
+}
+
+- (void)_updateSecureStreamOptions;
+{
     if (_secure) {
         NSMutableDictionary *SSLOptions = [[NSMutableDictionary alloc] init];
         
@@ -557,13 +594,17 @@ static __strong NSData *CRLFCRLF;
         
         // If we're using pinned certs, don't validate the certificate chain
         if ([_urlRequest SR_SSLPinnedCertificates].count) {
-            [SSLOptions setValue:[NSNumber numberWithBool:NO] forKey:(__bridge id)kCFStreamSSLValidatesCertificateChain];
+            [SSLOptions setValue:@NO forKey:(__bridge id)kCFStreamSSLValidatesCertificateChain];
         }
         
 #if DEBUG
-        [SSLOptions setValue:[NSNumber numberWithBool:NO] forKey:(__bridge id)kCFStreamSSLValidatesCertificateChain];
-        NSLog(@"SocketRocket: In debug mode.  Allowing connection to any root cert");
+        self.allowsUntrustedSSLCertificates = YES;
 #endif
+
+        if (self.allowsUntrustedSSLCertificates) {
+            [SSLOptions setValue:@NO forKey:(__bridge id)kCFStreamSSLValidatesCertificateChain];
+            SRFastLog(@"Allowing connection to any root cert");
+        }
         
         [_outputStream setProperty:SSLOptions
                             forKey:(__bridge id)kCFStreamPropertySSLSettings];
@@ -571,10 +612,49 @@ static __strong NSData *CRLFCRLF;
     
     _inputStream.delegate = self;
     _outputStream.delegate = self;
+    
+    [self setupNetworkServiceType:_urlRequest.networkServiceType];
+}
+
+- (void)setupNetworkServiceType:(NSURLRequestNetworkServiceType)requestNetworkServiceType
+{
+    NSString *networkServiceType;
+    switch (requestNetworkServiceType) {
+        case NSURLNetworkServiceTypeDefault:
+            break;
+        case NSURLNetworkServiceTypeVoIP: {
+            networkServiceType = NSStreamNetworkServiceTypeVoIP;
+#ifdef __IPHONE_9_0
+            if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_8_3) {
+                static dispatch_once_t predicate;
+                dispatch_once(&predicate, ^{
+                    NSLog(@"SocketRocket: %@ - this service type is deprecated in favor of using PushKit for VoIP control", networkServiceType);
+                });
+            }
+#endif
+            break;
+        }
+        case NSURLNetworkServiceTypeVideo:
+            networkServiceType = NSStreamNetworkServiceTypeVideo;
+            break;
+        case NSURLNetworkServiceTypeBackground:
+            networkServiceType = NSStreamNetworkServiceTypeBackground;
+            break;
+        case NSURLNetworkServiceTypeVoice:
+            networkServiceType = NSStreamNetworkServiceTypeVoice;
+            break;
+    }
+    
+    if (networkServiceType != nil) {
+        [_inputStream setProperty:networkServiceType forKey:NSStreamNetworkServiceType];
+        [_outputStream setProperty:networkServiceType forKey:NSStreamNetworkServiceType];
+    }
 }
 
 - (void)openConnection;
 {
+    [self _updateSecureStreamOptions];
+    
     if (!_scheduledRunloops.count) {
         [self scheduleInRunLoop:[NSRunLoop SR_networkRunLoop] forMode:NSDefaultRunLoopMode];
     }
@@ -1440,6 +1520,12 @@ static const size_t SRFrameHeaderOverhead = 32;
                 });
                 return;
             }
+            
+            if (aStream == _outputStream && _pinnedCertFound) {
+                dispatch_async(_workQueue, ^{
+                    [self didConnect];
+                });
+            }
         }
     }
 
@@ -1461,9 +1547,10 @@ static const size_t SRFrameHeaderOverhead = 32;
             }
             assert(_readBuffer);
             
-            if (self.readyState == SR_CONNECTING && aStream == _inputStream) {
+            if (!_secure && self.readyState == SR_CONNECTING && aStream == _inputStream) {
                 [self didConnect];
             }
+
             [self _pumpWriting];
             [self _pumpScanner];
             break;
@@ -1608,7 +1695,7 @@ static const size_t SRFrameHeaderOverhead = 32;
 @end
 
 
-@implementation  NSURLRequest (CertificateAdditions)
+@implementation  NSURLRequest (SRCertificateAdditions)
 
 - (NSArray *)SR_SSLPinnedCertificates;
 {
@@ -1617,7 +1704,7 @@ static const size_t SRFrameHeaderOverhead = 32;
 
 @end
 
-@implementation  NSMutableURLRequest (CertificateAdditions)
+@implementation  NSMutableURLRequest (SRCertificateAdditions)
 
 - (NSArray *)SR_SSLPinnedCertificates;
 {
@@ -1643,10 +1730,14 @@ static const size_t SRFrameHeaderOverhead = 32;
         scheme = @"http";
     }
     
-    if (self.port) {
-        return [NSString stringWithFormat:@"%@://%@:%@/", scheme, self.host, self.port];
+    BOOL portIsDefault = !self.port ||
+                         ([scheme isEqualToString:@"http"] && self.port.integerValue == 80) ||
+                         ([scheme isEqualToString:@"https"] && self.port.integerValue == 443);
+    
+    if (!portIsDefault) {
+        return [NSString stringWithFormat:@"%@://%@:%@", scheme, self.host, self.port];
     } else {
-        return [NSString stringWithFormat:@"%@://%@/", scheme, self.host];
+        return [NSString stringWithFormat:@"%@://%@", scheme, self.host];
     }
 }
 

+ 1 - 1
TestChat/TCViewController.m

@@ -7,7 +7,7 @@
 //
 
 #import "TCViewController.h"
-#import "SRWebSocket.h"
+#import <SocketRocket/SRWebSocket.h>
 #import "TCChatCell.h"
 
 @interface TCMessage : NSObject

+ 42 - 41
TestChatServer/go/chatroom.go

@@ -1,60 +1,61 @@
 package main
 
 import (
-    "code.google.com/p/go.net/websocket"
-    "net/http"
+	"code.google.com/p/go.net/websocket"
+	"net/http"
 )
 
+// Msg stores both the message and the connection
 type Msg struct {
-    sender *websocket.Conn
-    msg    string
+	sender *websocket.Conn
+	msg    string
 }
 
 func run(reg chan *websocket.Conn, unreg chan *websocket.Conn, msg chan Msg) {
-    conns := make(map[*websocket.Conn]int)
-    for {
-        select {
-        case c := <-reg:
-            conns[c] = 1
-        case c := <-unreg:
-            delete(conns, c)
-        case msg := <-msg:
-            for c := range conns {
-                if c != msg.sender {
-                    websocket.Message.Send(c, msg.msg)
-                }
-            }
-        }
-    }
+	conns := make(map[*websocket.Conn]int)
+	for {
+		select {
+		case c := <-reg:
+			conns[c] = 1
+		case c := <-unreg:
+			delete(conns, c)
+		case msg := <-msg:
+			for c := range conns {
+				if c != msg.sender {
+					websocket.Message.Send(c, msg.msg)
+				}
+			}
+		}
+	}
 }
 
 func newChatServer(reg chan *websocket.Conn, unreg chan *websocket.Conn, msg chan Msg) websocket.Handler {
-    return func(ws *websocket.Conn) {
-        reg <- ws
-        for {
-            var message string
-            err := websocket.Message.Receive(ws, &message)
-            if err != nil {
-                unreg <- ws
-                break
-            }
-            msg <- Msg{ws, message}
-        }
-    }
+	return func(ws *websocket.Conn) {
+		reg <- ws
+		for {
+			var message string
+			err := websocket.Message.Receive(ws, &message)
+			if err != nil {
+				unreg <- ws
+				break
+			}
+			msg <- Msg{ws, message}
+		}
+	}
 }
 
 func main() {
-    reg := make(chan *websocket.Conn)
-    unreg := make(chan *websocket.Conn)
-    msg := make(chan Msg)
+	reg := make(chan *websocket.Conn)
+	unreg := make(chan *websocket.Conn)
+	msg := make(chan Msg)
 
-    http.Handle("/chat", websocket.Handler(newChatServer(reg, unreg, msg)))
-    http.Handle("/", http.FileServer(http.Dir("../static")))
+	http.Handle("/chat", websocket.Handler(newChatServer(reg, unreg, msg)))
+	http.Handle("/", http.FileServer(http.Dir("../static")))
 
-    go run(reg, unreg, msg)
+	go run(reg, unreg, msg)
 
-    err := http.ListenAndServe(":9000", nil)
-    if err != nil {
-        panic("ListenAndServe: " + err.Error())
-    }
+	err := http.ListenAndServe(":9000", nil)
+	if err != nil {
+		panic("ListenAndServe: " + err.Error())
+	}
 }