Compare commits

...

24 Commits

Author SHA1 Message Date
Mike Lewis
95de1ea335 Moar cleanup 2015-08-07 17:32:28 -07:00
Mike Lewis
e3c402beab More unicode tests 2015-08-07 17:28:00 -07:00
Mike Lewis
f616386954 Making promise better 2015-08-07 13:38:57 -07:00
Mike Lewis
61b19ab633 Adding once 2015-08-07 10:52:07 -07:00
Mike Lewis
c62bfb90ad UTF8 Handling 2015-08-06 23:07:39 -07:00
Mike Lewis
d7078b082c Error ahndling 2015-08-06 15:01:05 -07:00
Mike Lewis
49c79072d2 Making API more JS-like 2015-08-05 16:38:18 -07:00
Mike Lewis
a797a0f568 Adding tests for getaddrinfo 2015-08-05 01:40:13 -07:00
Mike Lewis
7c6e18e858 Yeah 2015-08-04 23:04:35 -07:00
Mike Lewis
e6c3850c9b Promises are great 2015-08-04 23:02:48 -07:00
Mike Lewis
fe572dc752 Better promises 2015-08-04 21:03:26 -07:00
Mike Lewis
9b0d5134f8 More promise stuff 2015-08-03 23:48:37 -07:00
Mike Lewis
1883c521d6 Adding future library 2015-08-03 23:39:00 -07:00
Mike Lewis
5214ed5347 Getting shit working 2015-07-31 18:59:32 -07:00
Mike Lewis
7ea9d25976 Adding listening 2015-07-31 18:59:12 -07:00
Mike Lewis
5278664ab7 Merge remote-tracking branch 'origin/master' into lewis/dispatch-awesome 2015-07-30 16:46:50 -07:00
Mike Lewis
2a2ed772c3 More fixes and improvements 2013-01-16 23:51:24 -08:00
Mike Lewis
d237938434 Pew pew it works... kinda. 2013-01-16 23:11:11 -08:00
Mike Lewis
ac861d6ff2 Added test harness and it seems like things are kind of working 2013-01-16 00:29:30 -08:00
Mike Lewis
2ab4b7d421 The TLS seems to work
Cleaned up GCD so OS_OBJECT_USE_OBJC_RETAIN_RELEASE is optional
2013-01-15 23:49:26 -08:00
Mike Lewis
edd6faceed Added Non-working SecureIO 2013-01-13 11:48:49 -08:00
Mike Lewis
f58b21618c WiP 2013-01-12 23:40:03 -08:00
Mike Lewis
fdf93c6f9c Async Connection 2013-01-12 19:57:18 -08:00
Mike Lewis
72f7f81ff4 Porting some to ObjC++ and adding dispatch wrappers 2013-01-12 15:38:00 -08:00
51 changed files with 7544 additions and 124 deletions

View File

@ -107,6 +107,7 @@
- (NSUInteger)testCaseCount;
{
return 0;
if (self.invocation) {
return [super testCaseCount];
}

View File

@ -7,7 +7,7 @@
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>com.squareup.${PRODUCT_NAME:rfc1034identifier}</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>

View File

@ -0,0 +1,13 @@
//
// STRDispatchTest.h
// SocketRocket
//
// Created by Michael Lewis on 1/12/13.
//
//
#import <SenTestingKit/SenTestingKit.h>
@interface STRDispatchTest : SenTestCase
@end

View File

@ -0,0 +1,151 @@
//
// STRDispatchTest.m
// SocketRocket
//
// Created by Michael Lewis on 1/12/13.
//
//
extern "C" {
#import <SenTestingKit/SenTestingKit.h>
}
#include <Security/SecureTransport.h>
#include "DispatchIO.h"
#include "DispatchData.h"
#include "SecureIO.h"
using namespace squareup::dispatch;
@interface STRDispatchTest : SenTestCase
@end
@implementation STRDispatchTest
- (void)testConnect;
{
bool finished = false;
dispatch_queue_t workQueue = dispatch_queue_create("dispatch queue", DISPATCH_QUEUE_SERIAL);
Dial(workQueue, "localhost", "9932", dispatch_get_main_queue(), [&](dispatch_fd_t fd, int error_code, const char *error_message) {
NSLog(@"code: %d, msg: %s", error_code, error_message);
STAssertEquals(error_code, 0, @"Should not error but got %s", error_message);
finished = true;
});
[self runCurrentRunLoopUntilTestPasses:[&finished](){
return (BOOL)finished;
} timeout:100.0];
}
- (void)testSimpleDial;
{
RawIO *raw_io = nullptr;
bool finished = false;
auto cleanupBlock = [&finished](int error) {
finished = true;
};
SimpleDial("localhost", "9934", dispatch_get_main_queue(), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), [&raw_io, self, &finished](squareup::dispatch::RawIO *io, int error, const char *error_message) {
STAssertEquals(error, 0, @"Should not have errored, but got %s", error_message);
STAssertTrue(io != nullptr, @"io should be valid");
if (!io) {
finished = true;
return;
}
raw_io = io;
io->Write(Data("HELLO THERE!", dispatch_get_main_queue()), dispatch_get_main_queue(), [self, &raw_io](bool done, dispatch_data_t data, int error) {
STAssertEquals(error, 0, @"Error should == 0");
if (done) {
raw_io->Close(0);
}
});
}, cleanupBlock);
[self runCurrentRunLoopUntilTestPasses:[&finished](){
return (BOOL)finished;
} timeout:100.0];
}
- (void)testDialTLS;
{
SecureIO *raw_io = nullptr;
bool finished = false;
auto cleanupBlock = [&finished, raw_io](int error) {
dispatch_async(dispatch_get_main_queue(), [raw_io]{
delete raw_io;
});
NSLog(@"FINISHED");
finished = true;
};
SSLContextRef ctx = SSLCreateContext(CFAllocatorGetDefault(), kSSLClientSide, kSSLStreamType);
DialTLS("10.0.1.15", "10248", ctx, dispatch_get_main_queue(), dispatch_get_main_queue(), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), [&raw_io, self, &finished](squareup::dispatch::SecureIO *io, int error, const char *error_message) {
STAssertEquals(error, 0, @"Should not have errored, but got %s", error_message);
STAssertTrue(io != nullptr, @"io should be valid");
if (!io) {
finished = true;
return;
}
raw_io = io;
__block bool seenInner = false;
__block bool seenOuter = false;
//
// raw_io->Write(Data("HELLO THERE!\n", dispatch_get_main_queue()), ^(bool done, dispatch_data_t data, int error) {
// STAssertEquals(error, 0, @"Error should == 0");
// STAssertFalse(seenOuter, @"Should only see the outer once");
// if (done) {
// seenOuter = true;
// }
// if (done && !error) {
//
// }
// });
//
// raw_io->Write(Data("HELLO THERE2!\n", dispatch_get_main_queue()), ^(bool done, dispatch_data_t data, int error) {
// STAssertFalse(seenInner, @"Shouldn't have seen inner yet");
// if (done) {
// seenInner = done;
// }
// STAssertEquals(error, 0, @"Error should == 0");
// STAssertFalse(finished, @"Shouldn't have finished");
// });
raw_io->Read(SIZE_MAX, dispatch_get_main_queue(), ^(bool done, dispatch_data_t data, int error) {
if (!error) {
raw_io->Write(data, dispatch_get_main_queue(), ^(bool done, dispatch_data_t data, int error) {
});
} else {
STAssertTrue(error == ECANCELED, @"Server should terminate");
if (done && !error) {
raw_io->Close(0);
}
}
});
}, cleanupBlock);
[self runCurrentRunLoopUntilTestPasses:[&finished](){
return (BOOL)finished;
} timeout:100.0];
}
@end

View File

@ -1,4 +1,4 @@
//
//
// Copyright 2012 Square Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -7,17 +7,31 @@
objects = {
/* Begin PBXBuildFile section */
2725F85B16A29D18007018E9 /* SecureIO.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2725F85916A29D18007018E9 /* SecureIO.mm */; };
2725F85C16A29D18007018E9 /* SecureIO.h in Headers */ = {isa = PBXBuildFile; fileRef = 2725F85A16A29D18007018E9 /* SecureIO.h */; };
27CA136116A21E4D00A35C2D /* DispatchIO.mm in Sources */ = {isa = PBXBuildFile; fileRef = 27CA135F16A21E4D00A35C2D /* DispatchIO.mm */; };
27CA136216A21E4D00A35C2D /* DispatchIO.h in Headers */ = {isa = PBXBuildFile; fileRef = 27CA136016A21E4D00A35C2D /* DispatchIO.h */; };
27CA136616A2243000A35C2D /* DispatchData.mm in Sources */ = {isa = PBXBuildFile; fileRef = 27CA136416A2243000A35C2D /* DispatchData.mm */; };
27CA136716A2243000A35C2D /* DispatchData.h in Headers */ = {isa = PBXBuildFile; fileRef = 27CA136516A2243000A35C2D /* DispatchData.h */; };
27CA136A16A23AAE00A35C2D /* STRDispatchTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 27CA136916A23AAE00A35C2D /* STRDispatchTest.mm */; };
27DC4A9516A64EB800E9C084 /* Common.h in Headers */ = {isa = PBXBuildFile; fileRef = 27DC4A9416A64EB800E9C084 /* Common.h */; };
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 */; };
F60CC2A114D4EA0500A005E4 /* SRTWebSocketOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F60CC2A014D4EA0500A005E4 /* SRTWebSocketOperation.m */; };
F6191F3B1B6C4694003DF396 /* SystemShims.h in Headers */ = {isa = PBXBuildFile; fileRef = F6191F3A1B6C4694003DF396 /* SystemShims.h */; settings = {ATTRIBUTES = (Public, ); }; };
F6191F4D1B6C4694003DF396 /* SystemShims.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6191F381B6C4694003DF396 /* SystemShims.framework */; };
F6191F4E1B6C4694003DF396 /* SystemShims.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = F6191F381B6C4694003DF396 /* SystemShims.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
F6191F581B6C46B1003DF396 /* SystemShims.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6191F381B6C4694003DF396 /* SystemShims.framework */; };
F6191F5A1B6C46D2003DF396 /* SystemShims.m in Sources */ = {isa = PBXBuildFile; fileRef = F6191F591B6C46D2003DF396 /* SystemShims.m */; };
F6191F5C1B6C5598003DF396 /* IOTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6191F5B1B6C5598003DF396 /* IOTests.swift */; };
F61A0DC81625F44D00365EBD /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F61A0DC71625F44D00365EBD /* Default-568h@2x.png */; };
F62417E614D52F3C003CE997 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F62417E514D52F3C003CE997 /* UIKit.framework */; };
F62417E714D52F3C003CE997 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6B208301450F597009315AF /* Foundation.framework */; };
F62417E914D52F3C003CE997 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F62417E814D52F3C003CE997 /* CoreGraphics.framework */; };
F62417EF14D52F3C003CE997 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F62417ED14D52F3C003CE997 /* InfoPlist.strings */; };
F62417F114D52F3C003CE997 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F62417F014D52F3C003CE997 /* main.m */; };
F62417F514D52F3C003CE997 /* TCAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F62417F414D52F3C003CE997 /* TCAppDelegate.m */; };
F62417F514D52F3C003CE997 /* TCAppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = F62417F414D52F3C003CE997 /* TCAppDelegate.mm */; };
F62417F814D52F3C003CE997 /* MainStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F62417F614D52F3C003CE997 /* MainStoryboard.storyboard */; };
F62417FB14D52F3C003CE997 /* TCViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F62417FA14D52F3C003CE997 /* TCViewController.m */; };
F624180114D5300C003CE997 /* TCChatCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F624180014D5300C003CE997 /* TCChatCell.m */; };
@ -25,24 +39,57 @@
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 */; };
F6396B86153E67EC00345B5E /* SRWebSocket.mm in Sources */ = {isa = PBXBuildFile; fileRef = F6A12CD0145119B700C1D980 /* SRWebSocket.mm */; };
F668C899153E923C0044DBAC /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6396BA4153E6D7400345B5E /* CoreServices.framework */; };
F668C89A153E923C0044DBAC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6396BA1153E6D4800345B5E /* Foundation.framework */; };
F668C89B153E923C0044DBAC /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6396B9F153E6D3700345B5E /* Security.framework */; };
F668C8AA153E92F90044DBAC /* SRWebSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = F6A12CCF145119B700C1D980 /* SRWebSocket.h */; settings = {ATTRIBUTES = (Public, ); }; };
F69DAA171B6AEF6900B456D0 /* SocketRocketIO.h in Headers */ = {isa = PBXBuildFile; fileRef = F69DAA161B6AEF6900B456D0 /* SocketRocketIO.h */; settings = {ATTRIBUTES = (Public, ); }; };
F69DAA1E1B6AEF6900B456D0 /* SocketRocketIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F69DAA141B6AEF6900B456D0 /* SocketRocketIO.framework */; };
F69DAA231B6AEF6900B456D0 /* SocketRocketIOTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F69DAA221B6AEF6900B456D0 /* SocketRocketIOTests.swift */; };
F69DAA2C1B6AF09B00B456D0 /* IO.swift in Sources */ = {isa = PBXBuildFile; fileRef = F69DAA2B1B6AF09B00B456D0 /* IO.swift */; };
F69DAA2E1B6AF0CF00B456D0 /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = F69DAA2D1B6AF0CF00B456D0 /* Queue.swift */; };
F69DAA521B6AF53F00B456D0 /* QueueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F69DAA511B6AF53F00B456D0 /* QueueTests.swift */; };
F6A12CD1145119B700C1D980 /* SRWebSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = F6A12CCF145119B700C1D980 /* SRWebSocket.h */; settings = {ATTRIBUTES = (Public, ); }; };
F6A12CD2145119B700C1D980 /* SRWebSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = F6A12CD0145119B700C1D980 /* SRWebSocket.m */; };
F6A12CD2145119B700C1D980 /* SRWebSocket.mm in Sources */ = {isa = PBXBuildFile; fileRef = F6A12CD0145119B700C1D980 /* SRWebSocket.mm */; };
F6A2077C1B73E5B7002C359E /* Fixtures in Resources */ = {isa = PBXBuildFile; fileRef = F6A2077B1B73E5B7002C359E /* Fixtures */; };
F6A2077E1B73E5EA002C359E /* QueueStreamableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6A2077D1B73E5EA002C359E /* QueueStreamableTests.swift */; };
F6AD27211B70547200756377 /* Promise.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6AD27201B70547200756377 /* Promise.swift */; };
F6AD27231B70550C00756377 /* ErrorOptional.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6AD27221B70550C00756377 /* ErrorOptional.swift */; };
F6AD27251B705DAB00756377 /* Lock.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6AD27241B705DAB00756377 /* Lock.swift */; };
F6AD27271B707EFA00756377 /* PromisesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6AD27261B707EFA00756377 /* PromisesTests.swift */; };
F6AD390B1B73FE52001D93F5 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6AD390A1B73FE52001D93F5 /* Extensions.swift */; };
F6AE451D145906A70022AF3C /* libSocketRocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F6B2082D1450F597009315AF /* libSocketRocket.a */; };
F6AE4520145906B20022AF3C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6B208301450F597009315AF /* Foundation.framework */; };
F6AE45241459071C0022AF3C /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6A12CD51451231B00C1D980 /* CFNetwork.framework */; };
F6AE4528145907D30022AF3C /* SenTestCase+SRTAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = F6AE4527145907D30022AF3C /* SenTestCase+SRTAdditions.m */; };
F6B24CB61B75364100664E0B /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6B24CB51B75364100664E0B /* Error.swift */; };
F6BDA806145900D200FE3253 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6B208301450F597009315AF /* Foundation.framework */; };
F6BDA80C145900D200FE3253 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F6BDA80A145900D200FE3253 /* InfoPlist.strings */; };
F6BDA8161459016900FE3253 /* SRTAutobahnTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F6BDA8151459016900FE3253 /* SRTAutobahnTests.m */; };
F6C41C98145F7C6100641356 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F6C41C95145F7C4700641356 /* libicucore.dylib */; };
F6E95FF01B72DA580019AAF0 /* QueueStreamable.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6E95FEE1B72D8080019AAF0 /* QueueStreamable.swift */; };
F6FC407A1B74872D0007246E /* Unicode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6FC40791B74872D0007246E /* Unicode.swift */; };
F6FC407C1B7487630007246E /* UnicodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6FC407B1B7487630007246E /* UnicodeTests.swift */; };
F6FC407E1B751F330007246E /* Concurrent.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6FC407D1B751F330007246E /* Concurrent.swift */; };
F6FC40801B75244A0007246E /* ConcurrentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6FC407F1B75244A0007246E /* ConcurrentTests.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
F6191F4B1B6C4694003DF396 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F6B208241450F597009315AF /* Project object */;
proxyType = 1;
remoteGlobalIDString = F6191F371B6C4694003DF396;
remoteInfo = SystemShims;
};
F6191F561B6C46AD003DF396 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F6B208241450F597009315AF /* Project object */;
proxyType = 1;
remoteGlobalIDString = F6191F371B6C4694003DF396;
remoteInfo = SystemShims;
};
F62417D514D50869003CE997 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F6B208241450F597009315AF /* Project object */;
@ -50,11 +97,45 @@
remoteGlobalIDString = F6B2082C1450F597009315AF;
remoteInfo = SocketRocket;
};
F69DAA1F1B6AEF6900B456D0 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F6B208241450F597009315AF /* Project object */;
proxyType = 1;
remoteGlobalIDString = F69DAA131B6AEF6900B456D0;
remoteInfo = SocketRocketIO;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
F6191F541B6C4694003DF396 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
F6191F4E1B6C4694003DF396 /* SystemShims.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
2725F85916A29D18007018E9 /* SecureIO.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SecureIO.mm; sourceTree = "<group>"; };
2725F85A16A29D18007018E9 /* SecureIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecureIO.h; sourceTree = "<group>"; };
27CA135F16A21E4D00A35C2D /* DispatchIO.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DispatchIO.mm; sourceTree = "<group>"; };
27CA136016A21E4D00A35C2D /* DispatchIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DispatchIO.h; sourceTree = "<group>"; };
27CA136416A2243000A35C2D /* DispatchData.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DispatchData.mm; sourceTree = "<group>"; };
27CA136516A2243000A35C2D /* DispatchData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DispatchData.h; sourceTree = "<group>"; };
27CA136916A23AAE00A35C2D /* STRDispatchTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = STRDispatchTest.mm; sourceTree = "<group>"; };
27DC4A9416A64EB800E9C084 /* Common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Common.h; 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>"; };
F6191F381B6C4694003DF396 /* SystemShims.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SystemShims.framework; sourceTree = BUILT_PRODUCTS_DIR; };
F6191F3A1B6C4694003DF396 /* SystemShims.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SystemShims.h; sourceTree = "<group>"; };
F6191F3C1B6C4694003DF396 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
F6191F591B6C46D2003DF396 /* SystemShims.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SystemShims.m; sourceTree = "<group>"; };
F6191F5B1B6C5598003DF396 /* IOTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IOTests.swift; 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>"; };
F62417E314D52F3C003CE997 /* TestChat.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TestChat.app; sourceTree = BUILT_PRODUCTS_DIR; };
F62417E514D52F3C003CE997 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
@ -64,7 +145,7 @@
F62417F014D52F3C003CE997 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
F62417F214D52F3C003CE997 /* TestChat-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TestChat-Prefix.pch"; sourceTree = "<group>"; };
F62417F314D52F3C003CE997 /* TCAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TCAppDelegate.h; sourceTree = "<group>"; };
F62417F414D52F3C003CE997 /* TCAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TCAppDelegate.m; sourceTree = "<group>"; };
F62417F414D52F3C003CE997 /* TCAppDelegate.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = TCAppDelegate.mm; sourceTree = "<group>"; };
F62417F714D52F3C003CE997 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/MainStoryboard.storyboard; sourceTree = "<group>"; };
F62417F914D52F3C003CE997 /* TCViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TCViewController.h; sourceTree = "<group>"; };
F62417FA14D52F3C003CE997 /* TCViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TCViewController.m; sourceTree = "<group>"; };
@ -78,30 +159,60 @@
F668C885153E91210044DBAC /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
F668C886153E91210044DBAC /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
F668C889153E91210044DBAC /* SocketRocketOSX-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SocketRocketOSX-Info.plist"; sourceTree = "<group>"; };
F69DAA141B6AEF6900B456D0 /* SocketRocketIO.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SocketRocketIO.framework; sourceTree = BUILT_PRODUCTS_DIR; };
F69DAA161B6AEF6900B456D0 /* SocketRocketIO.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SocketRocketIO.h; sourceTree = "<group>"; };
F69DAA181B6AEF6900B456D0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
F69DAA1D1B6AEF6900B456D0 /* SocketRocketIOTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SocketRocketIOTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
F69DAA221B6AEF6900B456D0 /* SocketRocketIOTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocketRocketIOTests.swift; sourceTree = "<group>"; };
F69DAA241B6AEF6900B456D0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
F69DAA2B1B6AF09B00B456D0 /* IO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IO.swift; sourceTree = "<group>"; };
F69DAA2D1B6AF0CF00B456D0 /* Queue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Queue.swift; sourceTree = "<group>"; };
F69DAA511B6AF53F00B456D0 /* QueueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueueTests.swift; sourceTree = "<group>"; };
F6A12CCF145119B700C1D980 /* SRWebSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SRWebSocket.h; sourceTree = "<group>"; };
F6A12CD0145119B700C1D980 /* SRWebSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SRWebSocket.m; sourceTree = "<group>"; };
F6A12CD0145119B700C1D980 /* SRWebSocket.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SRWebSocket.mm; sourceTree = "<group>"; };
F6A12CD3145122FC00C1D980 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
F6A12CD51451231B00C1D980 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };
F6A2077B1B73E5B7002C359E /* Fixtures */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Fixtures; sourceTree = "<group>"; };
F6A2077D1B73E5EA002C359E /* QueueStreamableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueueStreamableTests.swift; sourceTree = "<group>"; };
F6AD27201B70547200756377 /* Promise.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Promise.swift; sourceTree = "<group>"; };
F6AD27221B70550C00756377 /* ErrorOptional.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ErrorOptional.swift; sourceTree = "<group>"; };
F6AD27241B705DAB00756377 /* Lock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Lock.swift; sourceTree = "<group>"; };
F6AD27261B707EFA00756377 /* PromisesTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PromisesTests.swift; sourceTree = "<group>"; };
F6AD390A1B73FE52001D93F5 /* Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = "<group>"; };
F6AE4526145907D30022AF3C /* SenTestCase+SRTAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SenTestCase+SRTAdditions.h"; sourceTree = "<group>"; };
F6AE4527145907D30022AF3C /* SenTestCase+SRTAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "SenTestCase+SRTAdditions.m"; sourceTree = "<group>"; };
F6B2082D1450F597009315AF /* libSocketRocket.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSocketRocket.a; sourceTree = BUILT_PRODUCTS_DIR; };
F6B208301450F597009315AF /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
F6B208341450F597009315AF /* SocketRocket-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SocketRocket-Prefix.pch"; sourceTree = "<group>"; };
F6B24CB51B75364100664E0B /* Error.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Error.swift; sourceTree = "<group>"; };
F6BDA802145900D200FE3253 /* SRWebSocketTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SRWebSocketTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
F6BDA809145900D200FE3253 /* SRWebSocketTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SRWebSocketTests-Info.plist"; sourceTree = "<group>"; };
F6BDA80B145900D200FE3253 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
F6BDA810145900D200FE3253 /* SRWebSocketTests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SRWebSocketTests-Prefix.pch"; sourceTree = "<group>"; };
F6BDA8151459016900FE3253 /* SRTAutobahnTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SRTAutobahnTests.m; sourceTree = "<group>"; };
F6C41C95145F7C4700641356 /* libicucore.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libicucore.dylib; path = usr/lib/libicucore.dylib; sourceTree = SDKROOT; };
F6E95FEE1B72D8080019AAF0 /* QueueStreamable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = QueueStreamable.swift; path = SocketRocketIOTests/QueueStreamable.swift; sourceTree = SOURCE_ROOT; };
F6FC40791B74872D0007246E /* Unicode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Unicode.swift; sourceTree = "<group>"; };
F6FC407B1B7487630007246E /* UnicodeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnicodeTests.swift; sourceTree = "<group>"; };
F6FC407D1B751F330007246E /* Concurrent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Concurrent.swift; sourceTree = "<group>"; };
F6FC407F1B75244A0007246E /* ConcurrentTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConcurrentTests.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
F6191F341B6C4694003DF396 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
F62417E014D52F3C003CE997 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
F62417E614D52F3C003CE997 /* UIKit.framework in Frameworks */,
F62417E714D52F3C003CE997 /* Foundation.framework in Frameworks */,
F6191F4D1B6C4694003DF396 /* SystemShims.framework in Frameworks */,
F62417E914D52F3C003CE997 /* CoreGraphics.framework in Frameworks */,
F624180214D532E0003CE997 /* libSocketRocket.a in Frameworks */,
F624180314D53449003CE997 /* CFNetwork.framework in Frameworks */,
@ -120,6 +231,22 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
F69DAA101B6AEF6900B456D0 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
F6191F581B6C46B1003DF396 /* SystemShims.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
F69DAA1A1B6AEF6900B456D0 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
F69DAA1E1B6AEF6900B456D0 /* SocketRocketIO.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
F6B2082A1450F597009315AF /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@ -145,12 +272,22 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
F6191F391B6C4694003DF396 /* SystemShims */ = {
isa = PBXGroup;
children = (
F6191F3A1B6C4694003DF396 /* SystemShims.h */,
F6191F3C1B6C4694003DF396 /* Info.plist */,
F6191F591B6C46D2003DF396 /* SystemShims.m */,
);
path = SystemShims;
sourceTree = "<group>";
};
F62417EA14D52F3C003CE997 /* TestChat */ = {
isa = PBXGroup;
children = (
F62417EB14D52F3C003CE997 /* Supporting Files */,
F62417F314D52F3C003CE997 /* TCAppDelegate.h */,
F62417F414D52F3C003CE997 /* TCAppDelegate.m */,
F62417F414D52F3C003CE997 /* TCAppDelegate.mm */,
F62417F614D52F3C003CE997 /* MainStoryboard.storyboard */,
F62417F914D52F3C003CE997 /* TCViewController.h */,
F62417FA14D52F3C003CE997 /* TCViewController.m */,
@ -200,6 +337,41 @@
path = SocketRocketOSX;
sourceTree = "<group>";
};
F69DAA151B6AEF6900B456D0 /* SocketRocketIO */ = {
isa = PBXGroup;
children = (
F69DAA161B6AEF6900B456D0 /* SocketRocketIO.h */,
F69DAA181B6AEF6900B456D0 /* Info.plist */,
F69DAA2B1B6AF09B00B456D0 /* IO.swift */,
F69DAA2D1B6AF0CF00B456D0 /* Queue.swift */,
F6AD27201B70547200756377 /* Promise.swift */,
F6AD27221B70550C00756377 /* ErrorOptional.swift */,
F6AD27241B705DAB00756377 /* Lock.swift */,
F6E95FEE1B72D8080019AAF0 /* QueueStreamable.swift */,
F6AD390A1B73FE52001D93F5 /* Extensions.swift */,
F6FC40791B74872D0007246E /* Unicode.swift */,
F6FC407D1B751F330007246E /* Concurrent.swift */,
F6B24CB51B75364100664E0B /* Error.swift */,
);
path = SocketRocketIO;
sourceTree = "<group>";
};
F69DAA211B6AEF6900B456D0 /* SocketRocketIOTests */ = {
isa = PBXGroup;
children = (
F6A2077B1B73E5B7002C359E /* Fixtures */,
F69DAA221B6AEF6900B456D0 /* SocketRocketIOTests.swift */,
F69DAA241B6AEF6900B456D0 /* Info.plist */,
F69DAA511B6AF53F00B456D0 /* QueueTests.swift */,
F6191F5B1B6C5598003DF396 /* IOTests.swift */,
F6AD27261B707EFA00756377 /* PromisesTests.swift */,
F6A2077D1B73E5EA002C359E /* QueueStreamableTests.swift */,
F6FC407B1B7487630007246E /* UnicodeTests.swift */,
F6FC407F1B75244A0007246E /* ConcurrentTests.swift */,
);
path = SocketRocketIOTests;
sourceTree = "<group>";
};
F6B208221450F597009315AF = {
isa = PBXGroup;
children = (
@ -207,6 +379,9 @@
F6BDA807145900D200FE3253 /* SRWebSocketTests */,
F62417EA14D52F3C003CE997 /* TestChat */,
F668C887153E91210044DBAC /* SocketRocketOSX */,
F69DAA151B6AEF6900B456D0 /* SocketRocketIO */,
F69DAA211B6AEF6900B456D0 /* SocketRocketIOTests */,
F6191F391B6C4694003DF396 /* SystemShims */,
F6B2082F1450F597009315AF /* Frameworks */,
F6B2082E1450F597009315AF /* Products */,
);
@ -221,6 +396,9 @@
F6BDA802145900D200FE3253 /* SRWebSocketTests.xctest */,
F62417E314D52F3C003CE997 /* TestChat.app */,
F668C880153E91210044DBAC /* SocketRocket.framework */,
F69DAA141B6AEF6900B456D0 /* SocketRocketIO.framework */,
F69DAA1D1B6AEF6900B456D0 /* SocketRocketIOTests.xctest */,
F6191F381B6C4694003DF396 /* SystemShims.framework */,
);
name = Products;
sourceTree = "<group>";
@ -245,7 +423,14 @@
children = (
F6B208331450F597009315AF /* Supporting Files */,
F6A12CCF145119B700C1D980 /* SRWebSocket.h */,
F6A12CD0145119B700C1D980 /* SRWebSocket.m */,
F6A12CD0145119B700C1D980 /* SRWebSocket.mm */,
27CA135F16A21E4D00A35C2D /* DispatchIO.mm */,
27CA136016A21E4D00A35C2D /* DispatchIO.h */,
2725F85916A29D18007018E9 /* SecureIO.mm */,
2725F85A16A29D18007018E9 /* SecureIO.h */,
27CA136416A2243000A35C2D /* DispatchData.mm */,
27CA136516A2243000A35C2D /* DispatchData.h */,
27DC4A9416A64EB800E9C084 /* Common.h */,
);
path = SocketRocket;
sourceTree = "<group>";
@ -268,6 +453,7 @@
F6AE4527145907D30022AF3C /* SenTestCase+SRTAdditions.m */,
F60CC29F14D4EA0500A005E4 /* SRTWebSocketOperation.h */,
F60CC2A014D4EA0500A005E4 /* SRTWebSocketOperation.m */,
27CA136916A23AAE00A35C2D /* STRDispatchTest.mm */,
);
path = SRWebSocketTests;
sourceTree = "<group>";
@ -284,6 +470,14 @@
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
F6191F351B6C4694003DF396 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
F6191F3B1B6C4694003DF396 /* SystemShims.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
F668C87D153E91210044DBAC /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
@ -292,17 +486,47 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
F69DAA111B6AEF6900B456D0 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
F69DAA171B6AEF6900B456D0 /* SocketRocketIO.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
F6B2082B1450F597009315AF /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
F6A12CD1145119B700C1D980 /* SRWebSocket.h in Headers */,
27CA136216A21E4D00A35C2D /* DispatchIO.h in Headers */,
27CA136716A2243000A35C2D /* DispatchData.h in Headers */,
2725F85C16A29D18007018E9 /* SecureIO.h in Headers */,
27DC4A9516A64EB800E9C084 /* Common.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
F6191F371B6C4694003DF396 /* SystemShims */ = {
isa = PBXNativeTarget;
buildConfigurationList = F6191F531B6C4694003DF396 /* Build configuration list for PBXNativeTarget "SystemShims" */;
buildPhases = (
F6191F331B6C4694003DF396 /* Sources */,
F6191F341B6C4694003DF396 /* Frameworks */,
F6191F351B6C4694003DF396 /* Headers */,
F6191F361B6C4694003DF396 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = SystemShims;
productName = SystemShims;
productReference = F6191F381B6C4694003DF396 /* SystemShims.framework */;
productType = "com.apple.product-type.framework";
};
F62417E214D52F3C003CE997 /* TestChat */ = {
isa = PBXNativeTarget;
buildConfigurationList = F62417FC14D52F3C003CE997 /* Build configuration list for PBXNativeTarget "TestChat" */;
@ -310,10 +534,12 @@
F62417DF14D52F3C003CE997 /* Sources */,
F62417E014D52F3C003CE997 /* Frameworks */,
F62417E114D52F3C003CE997 /* Resources */,
F6191F541B6C4694003DF396 /* Embed Frameworks */,
);
buildRules = (
);
dependencies = (
F6191F4C1B6C4694003DF396 /* PBXTargetDependency */,
);
name = TestChat;
productName = TestChat;
@ -338,6 +564,43 @@
productReference = F668C880153E91210044DBAC /* SocketRocket.framework */;
productType = "com.apple.product-type.framework";
};
F69DAA131B6AEF6900B456D0 /* SocketRocketIO */ = {
isa = PBXNativeTarget;
buildConfigurationList = F69DAA291B6AEF6900B456D0 /* Build configuration list for PBXNativeTarget "SocketRocketIO" */;
buildPhases = (
F69DAA0F1B6AEF6900B456D0 /* Sources */,
F69DAA101B6AEF6900B456D0 /* Frameworks */,
F69DAA111B6AEF6900B456D0 /* Headers */,
F69DAA121B6AEF6900B456D0 /* Resources */,
);
buildRules = (
);
dependencies = (
F6191F571B6C46AD003DF396 /* PBXTargetDependency */,
);
name = SocketRocketIO;
productName = SocketRocketIO;
productReference = F69DAA141B6AEF6900B456D0 /* SocketRocketIO.framework */;
productType = "com.apple.product-type.framework";
};
F69DAA1C1B6AEF6900B456D0 /* SocketRocketIOTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = F69DAA2A1B6AEF6900B456D0 /* Build configuration list for PBXNativeTarget "SocketRocketIOTests" */;
buildPhases = (
F69DAA191B6AEF6900B456D0 /* Sources */,
F69DAA1A1B6AEF6900B456D0 /* Frameworks */,
F69DAA1B1B6AEF6900B456D0 /* Resources */,
);
buildRules = (
);
dependencies = (
F69DAA201B6AEF6900B456D0 /* PBXTargetDependency */,
);
name = SocketRocketIOTests;
productName = SocketRocketIOTests;
productReference = F69DAA1D1B6AEF6900B456D0 /* SocketRocketIOTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
F6B2082C1450F597009315AF /* SocketRocket */ = {
isa = PBXNativeTarget;
buildConfigurationList = F6B2083A1450F597009315AF /* Build configuration list for PBXNativeTarget "SocketRocket" */;
@ -379,8 +642,20 @@
F6B208241450F597009315AF /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0700;
LastTestingUpgradeCheck = 0640;
LastUpgradeCheck = 0640;
LastUpgradeCheck = 0700;
TargetAttributes = {
F6191F371B6C4694003DF396 = {
CreatedOnToolsVersion = 7.0;
};
F69DAA131B6AEF6900B456D0 = {
CreatedOnToolsVersion = 7.0;
};
F69DAA1C1B6AEF6900B456D0 = {
CreatedOnToolsVersion = 7.0;
};
};
};
buildConfigurationList = F6B208271450F597009315AF /* Build configuration list for PBXProject "SocketRocket" */;
compatibilityVersion = "Xcode 3.2";
@ -398,11 +673,21 @@
F668C87F153E91210044DBAC /* SocketRocketOSX */,
F6BDA801145900D200FE3253 /* SRWebSocketTests */,
F62417E214D52F3C003CE997 /* TestChat */,
F69DAA131B6AEF6900B456D0 /* SocketRocketIO */,
F69DAA1C1B6AEF6900B456D0 /* SocketRocketIOTests */,
F6191F371B6C4694003DF396 /* SystemShims */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
F6191F361B6C4694003DF396 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
F62417E114D52F3C003CE997 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@ -420,6 +705,21 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
F69DAA121B6AEF6900B456D0 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
F69DAA1B1B6AEF6900B456D0 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
F6A2077C1B73E5B7002C359E /* Fixtures in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
F6BDA7FF145900D200FE3253 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@ -431,12 +731,20 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
F6191F331B6C4694003DF396 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
F6191F5A1B6C46D2003DF396 /* SystemShims.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
F62417DF14D52F3C003CE997 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
F62417F114D52F3C003CE997 /* main.m in Sources */,
F62417F514D52F3C003CE997 /* TCAppDelegate.m in Sources */,
F62417F514D52F3C003CE997 /* TCAppDelegate.mm in Sources */,
F62417FB14D52F3C003CE997 /* TCViewController.m in Sources */,
F624180114D5300C003CE997 /* TCChatCell.m in Sources */,
);
@ -446,7 +754,38 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
F6396B86153E67EC00345B5E /* SRWebSocket.m in Sources */,
F6396B86153E67EC00345B5E /* SRWebSocket.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
F69DAA0F1B6AEF6900B456D0 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
F6FC407E1B751F330007246E /* Concurrent.swift in Sources */,
F69DAA2C1B6AF09B00B456D0 /* IO.swift in Sources */,
F6E95FF01B72DA580019AAF0 /* QueueStreamable.swift in Sources */,
F6AD27251B705DAB00756377 /* Lock.swift in Sources */,
F69DAA2E1B6AF0CF00B456D0 /* Queue.swift in Sources */,
F6AD27231B70550C00756377 /* ErrorOptional.swift in Sources */,
F6AD27211B70547200756377 /* Promise.swift in Sources */,
F6AD390B1B73FE52001D93F5 /* Extensions.swift in Sources */,
F6B24CB61B75364100664E0B /* Error.swift in Sources */,
F6FC407A1B74872D0007246E /* Unicode.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
F69DAA191B6AEF6900B456D0 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
F6191F5C1B6C5598003DF396 /* IOTests.swift in Sources */,
F6A2077E1B73E5EA002C359E /* QueueStreamableTests.swift in Sources */,
F69DAA231B6AEF6900B456D0 /* SocketRocketIOTests.swift in Sources */,
F6FC407C1B7487630007246E /* UnicodeTests.swift in Sources */,
F69DAA521B6AF53F00B456D0 /* QueueTests.swift in Sources */,
F6AD27271B707EFA00756377 /* PromisesTests.swift in Sources */,
F6FC40801B75244A0007246E /* ConcurrentTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -454,7 +793,10 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
F6A12CD2145119B700C1D980 /* SRWebSocket.m in Sources */,
F6A12CD2145119B700C1D980 /* SRWebSocket.mm in Sources */,
27CA136116A21E4D00A35C2D /* DispatchIO.mm in Sources */,
27CA136616A2243000A35C2D /* DispatchData.mm in Sources */,
2725F85B16A29D18007018E9 /* SecureIO.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -465,17 +807,33 @@
F6BDA8161459016900FE3253 /* SRTAutobahnTests.m in Sources */,
F6AE4528145907D30022AF3C /* SenTestCase+SRTAdditions.m in Sources */,
F60CC2A114D4EA0500A005E4 /* SRTWebSocketOperation.m in Sources */,
27CA136A16A23AAE00A35C2D /* STRDispatchTest.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
F6191F4C1B6C4694003DF396 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = F6191F371B6C4694003DF396 /* SystemShims */;
targetProxy = F6191F4B1B6C4694003DF396 /* PBXContainerItemProxy */;
};
F6191F571B6C46AD003DF396 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = F6191F371B6C4694003DF396 /* SystemShims */;
targetProxy = F6191F561B6C46AD003DF396 /* PBXContainerItemProxy */;
};
F62417D614D50869003CE997 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = F6B2082C1450F597009315AF /* SocketRocket */;
targetProxy = F62417D514D50869003CE997 /* PBXContainerItemProxy */;
};
F69DAA201B6AEF6900B456D0 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = F69DAA131B6AEF6900B456D0 /* SocketRocketIO */;
targetProxy = F69DAA1F1B6AEF6900B456D0 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
@ -506,6 +864,75 @@
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
F6191F4F1B6C4694003DF396 /* 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_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
INFOPLIST_FILE = SystemShims/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MTL_ENABLE_DEBUG_INFO = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.squareup.SystemShims;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
F6191F501B6C4694003DF396 /* 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_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
INFOPLIST_FILE = SystemShims/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_BUNDLE_IDENTIFIER = com.squareup.SystemShims;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
F62417FD14D52F3C003CE997 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -517,8 +944,9 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "TestChat/TestChat-Prefix.pch";
INFOPLIST_FILE = "TestChat/TestChat-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 5.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_BUNDLE_IDENTIFIER = "com.squareup.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
WRAPPER_EXTENSION = app;
@ -536,9 +964,10 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "TestChat/TestChat-Prefix.pch";
INFOPLIST_FILE = "TestChat/TestChat-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 5.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_BUNDLE_IDENTIFIER = "com.squareup.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
WRAPPER_EXTENSION = app;
@ -564,6 +993,7 @@
LD_DYLIB_INSTALL_NAME = "@executable_path/../Frameworks/$(EXECUTABLE_PATH)";
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = "-ObjC";
PRODUCT_BUNDLE_IDENTIFIER = "com.squareup.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = SocketRocket;
SDKROOT = macosx;
WRAPPER_EXTENSION = framework;
@ -589,12 +1019,133 @@
INFOPLIST_FILE = "SocketRocketOSX/SocketRocketOSX-Info.plist";
LD_DYLIB_INSTALL_NAME = "@executable_path/../Frameworks/$(EXECUTABLE_PATH)";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_BUNDLE_IDENTIFIER = "com.squareup.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = SocketRocket;
SDKROOT = macosx;
WRAPPER_EXTENSION = framework;
};
name = Release;
};
F69DAA251B6AEF6900B456D0 /* 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_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
INFOPLIST_FILE = SocketRocketIO/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MTL_ENABLE_DEBUG_INFO = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.squareup.SocketRocketIO;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
F69DAA261B6AEF6900B456D0 /* 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_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
INFOPLIST_FILE = SocketRocketIO/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_BUNDLE_IDENTIFIER = com.squareup.SocketRocketIO;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
F69DAA271B6AEF6900B456D0 /* 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";
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
INFOPLIST_FILE = SocketRocketIOTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MTL_ENABLE_DEBUG_INFO = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.squareup.SocketRocketIOTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
F69DAA281B6AEF6900B456D0 /* 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;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
INFOPLIST_FILE = SocketRocketIOTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_BUNDLE_IDENTIFIER = com.squareup.SocketRocketIOTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
};
name = Release;
};
F6B208381450F597009315AF /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -610,6 +1161,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
@ -726,6 +1278,7 @@
"-framework",
XCTest,
);
PRODUCT_BUNDLE_IDENTIFIER = "com.squareup.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
@ -746,6 +1299,7 @@
"-framework",
XCTest,
);
PRODUCT_BUNDLE_IDENTIFIER = "com.squareup.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
@ -753,6 +1307,15 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
F6191F531B6C4694003DF396 /* Build configuration list for PBXNativeTarget "SystemShims" */ = {
isa = XCConfigurationList;
buildConfigurations = (
F6191F4F1B6C4694003DF396 /* Debug */,
F6191F501B6C4694003DF396 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
F62417FC14D52F3C003CE997 /* Build configuration list for PBXNativeTarget "TestChat" */ = {
isa = XCConfigurationList;
buildConfigurations = (
@ -771,6 +1334,24 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
F69DAA291B6AEF6900B456D0 /* Build configuration list for PBXNativeTarget "SocketRocketIO" */ = {
isa = XCConfigurationList;
buildConfigurations = (
F69DAA251B6AEF6900B456D0 /* Debug */,
F69DAA261B6AEF6900B456D0 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
F69DAA2A1B6AEF6900B456D0 /* Build configuration list for PBXNativeTarget "SocketRocketIOTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
F69DAA271B6AEF6900B456D0 /* Debug */,
F69DAA281B6AEF6900B456D0 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
F6B208271450F597009315AF /* Build configuration list for PBXProject "SocketRocket" */ = {
isa = XCConfigurationList;
buildConfigurations = (

View File

@ -0,0 +1,878 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
<<<<<<< HEAD
2725F85B16A29D18007018E9 /* SecureIO.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2725F85916A29D18007018E9 /* SecureIO.mm */; };
2725F85C16A29D18007018E9 /* SecureIO.h in Headers */ = {isa = PBXBuildFile; fileRef = 2725F85A16A29D18007018E9 /* SecureIO.h */; };
27CA136116A21E4D00A35C2D /* DispatchIO.mm in Sources */ = {isa = PBXBuildFile; fileRef = 27CA135F16A21E4D00A35C2D /* DispatchIO.mm */; };
27CA136216A21E4D00A35C2D /* DispatchIO.h in Headers */ = {isa = PBXBuildFile; fileRef = 27CA136016A21E4D00A35C2D /* DispatchIO.h */; };
27CA136616A2243000A35C2D /* DispatchData.mm in Sources */ = {isa = PBXBuildFile; fileRef = 27CA136416A2243000A35C2D /* DispatchData.mm */; };
27CA136716A2243000A35C2D /* DispatchData.h in Headers */ = {isa = PBXBuildFile; fileRef = 27CA136516A2243000A35C2D /* DispatchData.h */; };
27CA136A16A23AAE00A35C2D /* STRDispatchTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 27CA136916A23AAE00A35C2D /* STRDispatchTest.mm */; };
27DC4A9516A64EB800E9C084 /* Common.h in Headers */ = {isa = PBXBuildFile; fileRef = 27DC4A9416A64EB800E9C084 /* Common.h */; };
F6016C7C146124B20037BB3D /* base64.c in Sources */ = {isa = PBXBuildFile; fileRef = F6016C7B146124B20037BB3D /* base64.c */; };
F6016C7F146124ED0037BB3D /* base64.h in Headers */ = {isa = PBXBuildFile; fileRef = F6016C7E146124ED0037BB3D /* base64.h */; };
=======
>>>>>>> origin/master
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 */; };
F60CC2A114D4EA0500A005E4 /* SRTWebSocketOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F60CC2A014D4EA0500A005E4 /* SRTWebSocketOperation.m */; };
F61A0DC81625F44D00365EBD /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F61A0DC71625F44D00365EBD /* Default-568h@2x.png */; };
F62417E614D52F3C003CE997 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F62417E514D52F3C003CE997 /* UIKit.framework */; };
F62417E714D52F3C003CE997 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6B208301450F597009315AF /* Foundation.framework */; };
F62417E914D52F3C003CE997 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F62417E814D52F3C003CE997 /* CoreGraphics.framework */; };
F62417EF14D52F3C003CE997 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F62417ED14D52F3C003CE997 /* InfoPlist.strings */; };
F62417F114D52F3C003CE997 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F62417F014D52F3C003CE997 /* main.m */; };
F62417F514D52F3C003CE997 /* TCAppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = F62417F414D52F3C003CE997 /* TCAppDelegate.mm */; };
F62417F814D52F3C003CE997 /* MainStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F62417F614D52F3C003CE997 /* MainStoryboard.storyboard */; };
F62417FB14D52F3C003CE997 /* TCViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F62417FA14D52F3C003CE997 /* TCViewController.m */; };
F624180114D5300C003CE997 /* TCChatCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F624180014D5300C003CE997 /* TCChatCell.m */; };
F624180214D532E0003CE997 /* libSocketRocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F6B2082D1450F597009315AF /* libSocketRocket.a */; };
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 */; };
<<<<<<< HEAD
F6396B86153E67EC00345B5E /* SRWebSocket.mm in Sources */ = {isa = PBXBuildFile; fileRef = F6A12CD0145119B700C1D980 /* SRWebSocket.mm */; };
F6396B87153E67EC00345B5E /* base64.c in Sources */ = {isa = PBXBuildFile; fileRef = F6016C7B146124B20037BB3D /* base64.c */; };
F6396B88153E67EC00345B5E /* NSData+SRB64Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = F6572124146C7B6A00D6B8A9 /* NSData+SRB64Additions.m */; };
F6572126146C7B6A00D6B8A9 /* NSData+SRB64Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = F6572124146C7B6A00D6B8A9 /* NSData+SRB64Additions.m */; };
=======
F6396B86153E67EC00345B5E /* SRWebSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = F6A12CD0145119B700C1D980 /* SRWebSocket.m */; };
>>>>>>> origin/master
F668C899153E923C0044DBAC /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6396BA4153E6D7400345B5E /* CoreServices.framework */; };
F668C89A153E923C0044DBAC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6396BA1153E6D4800345B5E /* Foundation.framework */; };
F668C89B153E923C0044DBAC /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6396B9F153E6D3700345B5E /* Security.framework */; };
F668C8AA153E92F90044DBAC /* SRWebSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = F6A12CCF145119B700C1D980 /* SRWebSocket.h */; settings = {ATTRIBUTES = (Public, ); }; };
<<<<<<< HEAD
F6A12CD1145119B700C1D980 /* SRWebSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = F6A12CCF145119B700C1D980 /* SRWebSocket.h */; };
F6A12CD2145119B700C1D980 /* SRWebSocket.mm in Sources */ = {isa = PBXBuildFile; fileRef = F6A12CD0145119B700C1D980 /* SRWebSocket.mm */; };
=======
F6A12CD1145119B700C1D980 /* SRWebSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = F6A12CCF145119B700C1D980 /* SRWebSocket.h */; settings = {ATTRIBUTES = (Public, ); }; };
F6A12CD2145119B700C1D980 /* SRWebSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = F6A12CD0145119B700C1D980 /* SRWebSocket.m */; };
>>>>>>> origin/master
F6AE451D145906A70022AF3C /* libSocketRocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F6B2082D1450F597009315AF /* libSocketRocket.a */; };
F6AE4520145906B20022AF3C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6B208301450F597009315AF /* Foundation.framework */; };
F6AE45241459071C0022AF3C /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6A12CD51451231B00C1D980 /* CFNetwork.framework */; };
F6AE4528145907D30022AF3C /* SenTestCase+SRTAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = F6AE4527145907D30022AF3C /* SenTestCase+SRTAdditions.m */; };
F6BDA806145900D200FE3253 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6B208301450F597009315AF /* Foundation.framework */; };
F6BDA80C145900D200FE3253 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F6BDA80A145900D200FE3253 /* InfoPlist.strings */; };
F6BDA8161459016900FE3253 /* SRTAutobahnTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F6BDA8151459016900FE3253 /* SRTAutobahnTests.m */; };
F6C41C98145F7C6100641356 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F6C41C95145F7C4700641356 /* libicucore.dylib */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
F62417D514D50869003CE997 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F6B208241450F597009315AF /* Project object */;
proxyType = 1;
remoteGlobalIDString = F6B2082C1450F597009315AF;
remoteInfo = SocketRocket;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
<<<<<<< HEAD
2725F85916A29D18007018E9 /* SecureIO.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SecureIO.mm; sourceTree = "<group>"; };
2725F85A16A29D18007018E9 /* SecureIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecureIO.h; sourceTree = "<group>"; };
27CA135F16A21E4D00A35C2D /* DispatchIO.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DispatchIO.mm; sourceTree = "<group>"; };
27CA136016A21E4D00A35C2D /* DispatchIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DispatchIO.h; sourceTree = "<group>"; };
27CA136416A2243000A35C2D /* DispatchData.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DispatchData.mm; sourceTree = "<group>"; };
27CA136516A2243000A35C2D /* DispatchData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DispatchData.h; sourceTree = "<group>"; };
27CA136916A23AAE00A35C2D /* STRDispatchTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = STRDispatchTest.mm; sourceTree = "<group>"; };
27DC4A9416A64EB800E9C084 /* Common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Common.h; sourceTree = "<group>"; };
F6016C7B146124B20037BB3D /* base64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = base64.c; sourceTree = "<group>"; };
F6016C7E146124ED0037BB3D /* base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = base64.h; sourceTree = "<group>"; };
=======
>>>>>>> origin/master
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>"; };
F62417E314D52F3C003CE997 /* TestChat.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TestChat.app; sourceTree = BUILT_PRODUCTS_DIR; };
F62417E514D52F3C003CE997 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
F62417E814D52F3C003CE997 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
F62417EC14D52F3C003CE997 /* TestChat-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "TestChat-Info.plist"; sourceTree = "<group>"; };
F62417EE14D52F3C003CE997 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
F62417F014D52F3C003CE997 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
F62417F214D52F3C003CE997 /* TestChat-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TestChat-Prefix.pch"; sourceTree = "<group>"; };
F62417F314D52F3C003CE997 /* TCAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TCAppDelegate.h; sourceTree = "<group>"; };
F62417F414D52F3C003CE997 /* TCAppDelegate.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = TCAppDelegate.mm; sourceTree = "<group>"; };
F62417F714D52F3C003CE997 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/MainStoryboard.storyboard; sourceTree = "<group>"; };
F62417F914D52F3C003CE997 /* TCViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TCViewController.h; sourceTree = "<group>"; };
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>"; };
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; };
F668C880153E91210044DBAC /* SocketRocket.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SocketRocket.framework; sourceTree = BUILT_PRODUCTS_DIR; };
F668C884153E91210044DBAC /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
F668C885153E91210044DBAC /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
F668C886153E91210044DBAC /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
F668C889153E91210044DBAC /* SocketRocketOSX-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SocketRocketOSX-Info.plist"; sourceTree = "<group>"; };
F6A12CCF145119B700C1D980 /* SRWebSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SRWebSocket.h; sourceTree = "<group>"; };
F6A12CD0145119B700C1D980 /* SRWebSocket.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SRWebSocket.mm; sourceTree = "<group>"; };
F6A12CD3145122FC00C1D980 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
F6A12CD51451231B00C1D980 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };
F6AE4526145907D30022AF3C /* SenTestCase+SRTAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SenTestCase+SRTAdditions.h"; sourceTree = "<group>"; };
F6AE4527145907D30022AF3C /* SenTestCase+SRTAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "SenTestCase+SRTAdditions.m"; sourceTree = "<group>"; };
F6B2082D1450F597009315AF /* libSocketRocket.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSocketRocket.a; sourceTree = BUILT_PRODUCTS_DIR; };
F6B208301450F597009315AF /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
F6B208341450F597009315AF /* SocketRocket-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SocketRocket-Prefix.pch"; sourceTree = "<group>"; };
F6BDA802145900D200FE3253 /* SRWebSocketTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SRWebSocketTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
F6BDA809145900D200FE3253 /* SRWebSocketTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SRWebSocketTests-Info.plist"; sourceTree = "<group>"; };
F6BDA80B145900D200FE3253 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
F6BDA810145900D200FE3253 /* SRWebSocketTests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SRWebSocketTests-Prefix.pch"; sourceTree = "<group>"; };
F6BDA8151459016900FE3253 /* SRTAutobahnTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SRTAutobahnTests.m; sourceTree = "<group>"; };
F6C41C95145F7C4700641356 /* libicucore.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libicucore.dylib; path = usr/lib/libicucore.dylib; sourceTree = SDKROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
F62417E014D52F3C003CE997 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
F62417E614D52F3C003CE997 /* UIKit.framework in Frameworks */,
F62417E714D52F3C003CE997 /* Foundation.framework in Frameworks */,
F62417E914D52F3C003CE997 /* CoreGraphics.framework in Frameworks */,
F624180214D532E0003CE997 /* libSocketRocket.a in Frameworks */,
F624180314D53449003CE997 /* CFNetwork.framework in Frameworks */,
F624180414D53449003CE997 /* Security.framework in Frameworks */,
F624180614D53451003CE997 /* libicucore.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
F668C87C153E91210044DBAC /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
F668C899153E923C0044DBAC /* CoreServices.framework in Frameworks */,
F668C89A153E923C0044DBAC /* Foundation.framework in Frameworks */,
F668C89B153E923C0044DBAC /* Security.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
F6B2082A1450F597009315AF /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
F6AE4520145906B20022AF3C /* Foundation.framework in Frameworks */,
F6016C8914620ECC0037BB3D /* Security.framework in Frameworks */,
F6016C8A1462143C0037BB3D /* CFNetwork.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
F6BDA7FE145900D200FE3253 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
F6C41C98145F7C6100641356 /* libicucore.dylib in Frameworks */,
F6BDA806145900D200FE3253 /* Foundation.framework in Frameworks */,
F6AE451D145906A70022AF3C /* libSocketRocket.a in Frameworks */,
F6AE45241459071C0022AF3C /* CFNetwork.framework in Frameworks */,
F6016C8814620EC70037BB3D /* Security.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
F62417EA14D52F3C003CE997 /* TestChat */ = {
isa = PBXGroup;
children = (
F62417EB14D52F3C003CE997 /* Supporting Files */,
F62417F314D52F3C003CE997 /* TCAppDelegate.h */,
F62417F414D52F3C003CE997 /* TCAppDelegate.mm */,
F62417F614D52F3C003CE997 /* MainStoryboard.storyboard */,
F62417F914D52F3C003CE997 /* TCViewController.h */,
F62417FA14D52F3C003CE997 /* TCViewController.m */,
F62417FF14D5300C003CE997 /* TCChatCell.h */,
F624180014D5300C003CE997 /* TCChatCell.m */,
);
path = TestChat;
sourceTree = "<group>";
};
F62417EB14D52F3C003CE997 /* Supporting Files */ = {
isa = PBXGroup;
children = (
F61A0DC71625F44D00365EBD /* Default-568h@2x.png */,
F62417EC14D52F3C003CE997 /* TestChat-Info.plist */,
F62417ED14D52F3C003CE997 /* InfoPlist.strings */,
F62417F014D52F3C003CE997 /* main.m */,
F62417F214D52F3C003CE997 /* TestChat-Prefix.pch */,
);
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>";
};
F668C883153E91210044DBAC /* Other Frameworks */ = {
isa = PBXGroup;
children = (
F668C884153E91210044DBAC /* AppKit.framework */,
F668C885153E91210044DBAC /* CoreData.framework */,
F668C886153E91210044DBAC /* Foundation.framework */,
);
name = "Other Frameworks";
sourceTree = "<group>";
};
F668C887153E91210044DBAC /* SocketRocketOSX */ = {
isa = PBXGroup;
children = (
F668C889153E91210044DBAC /* SocketRocketOSX-Info.plist */,
);
path = SocketRocketOSX;
sourceTree = "<group>";
};
F6B208221450F597009315AF = {
isa = PBXGroup;
children = (
F6B208321450F597009315AF /* SocketRocket */,
F6BDA807145900D200FE3253 /* SRWebSocketTests */,
F62417EA14D52F3C003CE997 /* TestChat */,
F668C887153E91210044DBAC /* SocketRocketOSX */,
F6B2082F1450F597009315AF /* Frameworks */,
F6B2082E1450F597009315AF /* Products */,
);
indentWidth = 4;
sourceTree = "<group>";
tabWidth = 4;
};
F6B2082E1450F597009315AF /* Products */ = {
isa = PBXGroup;
children = (
F6B2082D1450F597009315AF /* libSocketRocket.a */,
F6BDA802145900D200FE3253 /* SRWebSocketTests.xctest */,
F62417E314D52F3C003CE997 /* TestChat.app */,
F668C880153E91210044DBAC /* SocketRocket.framework */,
);
name = Products;
sourceTree = "<group>";
};
F6B2082F1450F597009315AF /* Frameworks */ = {
isa = PBXGroup;
children = (
F6396BA3153E6D4D00345B5E /* OSX Frameworks */,
F6C41C95145F7C4700641356 /* libicucore.dylib */,
F6A12CD51451231B00C1D980 /* CFNetwork.framework */,
F6A12CD3145122FC00C1D980 /* Security.framework */,
F6B208301450F597009315AF /* Foundation.framework */,
F62417E514D52F3C003CE997 /* UIKit.framework */,
F62417E814D52F3C003CE997 /* CoreGraphics.framework */,
F668C883153E91210044DBAC /* Other Frameworks */,
);
name = Frameworks;
sourceTree = "<group>";
};
F6B208321450F597009315AF /* SocketRocket */ = {
isa = PBXGroup;
children = (
F6B208331450F597009315AF /* Supporting Files */,
F6A12CCF145119B700C1D980 /* SRWebSocket.h */,
<<<<<<< HEAD
F6A12CD0145119B700C1D980 /* SRWebSocket.mm */,
F6572123146C7B6A00D6B8A9 /* NSData+SRB64Additions.h */,
F6572124146C7B6A00D6B8A9 /* NSData+SRB64Additions.m */,
27CA135F16A21E4D00A35C2D /* DispatchIO.mm */,
27CA136016A21E4D00A35C2D /* DispatchIO.h */,
2725F85916A29D18007018E9 /* SecureIO.mm */,
2725F85A16A29D18007018E9 /* SecureIO.h */,
27CA136416A2243000A35C2D /* DispatchData.mm */,
27CA136516A2243000A35C2D /* DispatchData.h */,
27DC4A9416A64EB800E9C084 /* Common.h */,
=======
F6A12CD0145119B700C1D980 /* SRWebSocket.m */,
>>>>>>> origin/master
);
path = SocketRocket;
sourceTree = "<group>";
};
F6B208331450F597009315AF /* Supporting Files */ = {
isa = PBXGroup;
children = (
F6B208341450F597009315AF /* SocketRocket-Prefix.pch */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
F6BDA807145900D200FE3253 /* SRWebSocketTests */ = {
isa = PBXGroup;
children = (
F6BDA808145900D200FE3253 /* Supporting Files */,
F6BDA8151459016900FE3253 /* SRTAutobahnTests.m */,
F6BDA810145900D200FE3253 /* SRWebSocketTests-Prefix.pch */,
F6AE4526145907D30022AF3C /* SenTestCase+SRTAdditions.h */,
F6AE4527145907D30022AF3C /* SenTestCase+SRTAdditions.m */,
F60CC29F14D4EA0500A005E4 /* SRTWebSocketOperation.h */,
F60CC2A014D4EA0500A005E4 /* SRTWebSocketOperation.m */,
27CA136916A23AAE00A35C2D /* STRDispatchTest.mm */,
);
path = SRWebSocketTests;
sourceTree = "<group>";
};
F6BDA808145900D200FE3253 /* Supporting Files */ = {
isa = PBXGroup;
children = (
F6BDA809145900D200FE3253 /* SRWebSocketTests-Info.plist */,
F6BDA80A145900D200FE3253 /* InfoPlist.strings */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
F668C87D153E91210044DBAC /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
F668C8AA153E92F90044DBAC /* SRWebSocket.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
F6B2082B1450F597009315AF /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
F6A12CD1145119B700C1D980 /* SRWebSocket.h in Headers */,
<<<<<<< HEAD
F6016C7F146124ED0037BB3D /* base64.h in Headers */,
27CA136216A21E4D00A35C2D /* DispatchIO.h in Headers */,
27CA136716A2243000A35C2D /* DispatchData.h in Headers */,
2725F85C16A29D18007018E9 /* SecureIO.h in Headers */,
27DC4A9516A64EB800E9C084 /* Common.h in Headers */,
=======
>>>>>>> origin/master
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
F62417E214D52F3C003CE997 /* TestChat */ = {
isa = PBXNativeTarget;
buildConfigurationList = F62417FC14D52F3C003CE997 /* Build configuration list for PBXNativeTarget "TestChat" */;
buildPhases = (
F62417DF14D52F3C003CE997 /* Sources */,
F62417E014D52F3C003CE997 /* Frameworks */,
F62417E114D52F3C003CE997 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = TestChat;
productName = TestChat;
productReference = F62417E314D52F3C003CE997 /* TestChat.app */;
productType = "com.apple.product-type.application";
};
F668C87F153E91210044DBAC /* SocketRocketOSX */ = {
isa = PBXNativeTarget;
buildConfigurationList = F668C891153E91210044DBAC /* Build configuration list for PBXNativeTarget "SocketRocketOSX" */;
buildPhases = (
F6396B85153E67EC00345B5E /* Sources */,
F668C87C153E91210044DBAC /* Frameworks */,
F668C87D153E91210044DBAC /* Headers */,
F668C87E153E91210044DBAC /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = SocketRocketOSX;
productName = SocketRocketOSX;
productReference = F668C880153E91210044DBAC /* SocketRocket.framework */;
productType = "com.apple.product-type.framework";
};
F6B2082C1450F597009315AF /* SocketRocket */ = {
isa = PBXNativeTarget;
buildConfigurationList = F6B2083A1450F597009315AF /* Build configuration list for PBXNativeTarget "SocketRocket" */;
buildPhases = (
F6B208291450F597009315AF /* Sources */,
F6B2082A1450F597009315AF /* Frameworks */,
F6B2082B1450F597009315AF /* Headers */,
);
buildRules = (
);
dependencies = (
);
name = SocketRocket;
productName = SocketRocket;
productReference = F6B2082D1450F597009315AF /* libSocketRocket.a */;
productType = "com.apple.product-type.library.static";
};
F6BDA801145900D200FE3253 /* SRWebSocketTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = F6BDA813145900D200FE3253 /* Build configuration list for PBXNativeTarget "SRWebSocketTests" */;
buildPhases = (
F6BDA7FD145900D200FE3253 /* Sources */,
F6BDA7FE145900D200FE3253 /* Frameworks */,
F6BDA7FF145900D200FE3253 /* Resources */,
);
buildRules = (
);
dependencies = (
F62417D614D50869003CE997 /* PBXTargetDependency */,
);
name = SRWebSocketTests;
productName = SRWebSocketTests;
productReference = F6BDA802145900D200FE3253 /* SRWebSocketTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
F6B208241450F597009315AF /* Project object */ = {
isa = PBXProject;
attributes = {
LastTestingUpgradeCheck = 0640;
LastUpgradeCheck = 0640;
};
buildConfigurationList = F6B208271450F597009315AF /* Build configuration list for PBXProject "SocketRocket" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = F6B208221450F597009315AF;
productRefGroup = F6B2082E1450F597009315AF /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
F6B2082C1450F597009315AF /* SocketRocket */,
F668C87F153E91210044DBAC /* SocketRocketOSX */,
F6BDA801145900D200FE3253 /* SRWebSocketTests */,
F62417E214D52F3C003CE997 /* TestChat */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
F62417E114D52F3C003CE997 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
F62417EF14D52F3C003CE997 /* InfoPlist.strings in Resources */,
F62417F814D52F3C003CE997 /* MainStoryboard.storyboard in Resources */,
F61A0DC81625F44D00365EBD /* Default-568h@2x.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
F668C87E153E91210044DBAC /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
F6BDA7FF145900D200FE3253 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
F6BDA80C145900D200FE3253 /* InfoPlist.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
F62417DF14D52F3C003CE997 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
F62417F114D52F3C003CE997 /* main.m in Sources */,
F62417F514D52F3C003CE997 /* TCAppDelegate.mm in Sources */,
F62417FB14D52F3C003CE997 /* TCViewController.m in Sources */,
F624180114D5300C003CE997 /* TCChatCell.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
F6396B85153E67EC00345B5E /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
<<<<<<< HEAD
F6396B86153E67EC00345B5E /* SRWebSocket.mm in Sources */,
F6396B87153E67EC00345B5E /* base64.c in Sources */,
F6396B88153E67EC00345B5E /* NSData+SRB64Additions.m in Sources */,
=======
F6396B86153E67EC00345B5E /* SRWebSocket.m in Sources */,
>>>>>>> origin/master
);
runOnlyForDeploymentPostprocessing = 0;
};
F6B208291450F597009315AF /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
<<<<<<< HEAD
F6A12CD2145119B700C1D980 /* SRWebSocket.mm in Sources */,
F6016C7C146124B20037BB3D /* base64.c in Sources */,
F6572126146C7B6A00D6B8A9 /* NSData+SRB64Additions.m in Sources */,
27CA136116A21E4D00A35C2D /* DispatchIO.mm in Sources */,
27CA136616A2243000A35C2D /* DispatchData.mm in Sources */,
2725F85B16A29D18007018E9 /* SecureIO.mm in Sources */,
=======
F6A12CD2145119B700C1D980 /* SRWebSocket.m in Sources */,
>>>>>>> origin/master
);
runOnlyForDeploymentPostprocessing = 0;
};
F6BDA7FD145900D200FE3253 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
F6BDA8161459016900FE3253 /* SRTAutobahnTests.m in Sources */,
F6AE4528145907D30022AF3C /* SenTestCase+SRTAdditions.m in Sources */,
F60CC2A114D4EA0500A005E4 /* SRTWebSocketOperation.m in Sources */,
27CA136A16A23AAE00A35C2D /* STRDispatchTest.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
F62417D614D50869003CE997 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = F6B2082C1450F597009315AF /* SocketRocket */;
targetProxy = F62417D514D50869003CE997 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
F62417ED14D52F3C003CE997 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
F62417EE14D52F3C003CE997 /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
F62417F614D52F3C003CE997 /* MainStoryboard.storyboard */ = {
isa = PBXVariantGroup;
children = (
F62417F714D52F3C003CE997 /* en */,
);
name = MainStoryboard.storyboard;
sourceTree = "<group>";
};
F6BDA80A145900D200FE3253 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
F6BDA80B145900D200FE3253 /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
F62417FD14D52F3C003CE997 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\"$(DEVELOPER_FRAMEWORKS_DIR)\"",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "TestChat/TestChat-Prefix.pch";
INFOPLIST_FILE = "TestChat/TestChat-Info.plist";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
WRAPPER_EXTENSION = app;
};
name = Debug;
};
F62417FE14D52F3C003CE997 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\"$(DEVELOPER_FRAMEWORKS_DIR)\"",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "TestChat/TestChat-Prefix.pch";
INFOPLIST_FILE = "TestChat/TestChat-Info.plist";
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
WRAPPER_EXTENSION = app;
};
name = Release;
};
F668C892153E91210044DBAC /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks\"",
);
FRAMEWORK_VERSION = A;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "SocketRocket/SocketRocket-Prefix.pch";
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
INFOPLIST_FILE = "SocketRocketOSX/SocketRocketOSX-Info.plist";
LD_DYLIB_INSTALL_NAME = "@executable_path/../Frameworks/$(EXECUTABLE_PATH)";
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = SocketRocket;
SDKROOT = macosx;
WRAPPER_EXTENSION = framework;
};
name = Debug;
};
F668C893153E91210044DBAC /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks\"",
);
FRAMEWORK_VERSION = A;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "SocketRocket/SocketRocket-Prefix.pch";
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
INFOPLIST_FILE = "SocketRocketOSX/SocketRocketOSX-Info.plist";
LD_DYLIB_INSTALL_NAME = "@executable_path/../Frameworks/$(EXECUTABLE_PATH)";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = SocketRocket;
SDKROOT = macosx;
WRAPPER_EXTENSION = framework;
};
name = Release;
};
F6B208381450F597009315AF /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_SIGN_COMPARE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 5.1;
ONLY_ACTIVE_ARCH = YES;
RUN_CLANG_STATIC_ANALYZER = YES;
SDKROOT = iphoneos6.0;
};
name = Debug;
};
F6B208391450F597009315AF /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_NO_COMMON_BLOCKS = YES;
GCC_PREPROCESSOR_DEFINITIONS = (
NDEBUG,
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_SIGN_COMPARE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 5.1;
RUN_CLANG_STATIC_ANALYZER = YES;
SDKROOT = iphoneos6.0;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
F6B2083B1450F597009315AF /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_OBJC_ARC = YES;
DSTROOT = /tmp/SocketRocket.dst;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "SocketRocket/SocketRocket-Prefix.pch";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"\"$(DEVELOPER_DIR)/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator7.1.sdk/usr/lib/system\"",
"\"$(DEVELOPER_DIR)/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator7.1.sdk/usr/lib\"",
);
OTHER_LDFLAGS = "-Licucore";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
};
name = Debug;
};
F6B2083C1450F597009315AF /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_OBJC_ARC = YES;
DSTROOT = /tmp/SocketRocket.dst;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "SocketRocket/SocketRocket-Prefix.pch";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"\"$(DEVELOPER_DIR)/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator7.1.sdk/usr/lib/system\"",
"\"$(DEVELOPER_DIR)/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator7.1.sdk/usr/lib\"",
);
OTHER_LDFLAGS = "-Licucore";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
};
name = Release;
};
F6BDA811145900D200FE3253 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "SRWebSocketTests/SRWebSocketTests-Prefix.pch";
INFOPLIST_FILE = "SRWebSocketTests/SRWebSocketTests-Info.plist";
OTHER_LDFLAGS = (
"-all_load",
"-ObjC",
"-framework",
XCTest,
);
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
F6BDA812145900D200FE3253 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "SRWebSocketTests/SRWebSocketTests-Prefix.pch";
INFOPLIST_FILE = "SRWebSocketTests/SRWebSocketTests-Info.plist";
OTHER_LDFLAGS = (
"-all_load",
"-ObjC",
"-framework",
XCTest,
);
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
F62417FC14D52F3C003CE997 /* Build configuration list for PBXNativeTarget "TestChat" */ = {
isa = XCConfigurationList;
buildConfigurations = (
F62417FD14D52F3C003CE997 /* Debug */,
F62417FE14D52F3C003CE997 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
F668C891153E91210044DBAC /* Build configuration list for PBXNativeTarget "SocketRocketOSX" */ = {
isa = XCConfigurationList;
buildConfigurations = (
F668C892153E91210044DBAC /* Debug */,
F668C893153E91210044DBAC /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
F6B208271450F597009315AF /* Build configuration list for PBXProject "SocketRocket" */ = {
isa = XCConfigurationList;
buildConfigurations = (
F6B208381450F597009315AF /* Debug */,
F6B208391450F597009315AF /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
F6B2083A1450F597009315AF /* Build configuration list for PBXNativeTarget "SocketRocket" */ = {
isa = XCConfigurationList;
buildConfigurations = (
F6B2083B1450F597009315AF /* Debug */,
F6B2083C1450F597009315AF /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
F6BDA813145900D200FE3253 /* Build configuration list for PBXNativeTarget "SRWebSocketTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
F6BDA811145900D200FE3253 /* Debug */,
F6BDA812145900D200FE3253 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = F6B208241450F597009315AF /* Project object */;
}

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0630"
LastUpgradeVersion = "0700"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
@ -37,10 +37,10 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "NO"
buildConfiguration = "Debug">
shouldUseLaunchSchemeArgsEnv = "NO">
<PreActions>
<ExecutionAction
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
@ -89,6 +89,17 @@
BlueprintName = "SRWebSocketTests"
ReferencedContainer = "container:SocketRocket.xcodeproj">
</BuildableReference>
<SkippedTests>
<Test
Identifier = "SRTAutobahnTests">
</Test>
<Test
Identifier = "STRDispatchTest/testConnect">
</Test>
<Test
Identifier = "STRDispatchTest/testSimpleDial">
</Test>
</SkippedTests>
</TestableReference>
</Testables>
<MacroExpansion>
@ -107,15 +118,18 @@
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
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
@ -127,6 +141,11 @@
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
<AdditionalOption
key = "DYLD_INSERT_LIBRARIES"
value = "/usr/lib/libgmalloc.dylib"
isEnabled = "YES">
</AdditionalOption>
<AdditionalOption
key = "NSZombieEnabled"
value = "YES"
@ -150,10 +169,10 @@
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0630"
LastUpgradeVersion = "0700"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@ -23,21 +23,24 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
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
@ -52,10 +55,10 @@
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0630"
LastUpgradeVersion = "0700"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@ -23,10 +23,10 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "NO"
buildConfiguration = "Debug">
shouldUseLaunchSchemeArgsEnv = "NO">
<Testables>
<TestableReference
skipped = "NO">
@ -39,15 +39,18 @@
</BuildableReference>
</TestableReference>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
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
@ -82,10 +85,10 @@
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction

View File

@ -24,7 +24,7 @@
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
@ -62,23 +62,12 @@
<AdditionalOption
key = "NSZombieEnabled"
value = "YES"
isEnabled = "YES">
</AdditionalOption>
<AdditionalOption
key = "OBJC_PRINT_EXCEPTIONS"
value = "YES"
isEnabled = "YES">
</AdditionalOption>
<AdditionalOption
key = "MallocGuardEdges"
value = ""
isEnabled = "YES">
</AdditionalOption>
<AdditionalOption
key = "MallocScribble"
value = ""
isEnabled = "YES">
</AdditionalOption>
</AdditionalOptions>
</LaunchAction>
<ProfileAction

View File

@ -0,0 +1,114 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0630"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "F62417E214D52F3C003CE997"
BuildableName = "TestChat.app"
BlueprintName = "TestChat"
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>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "F62417E214D52F3C003CE997"
BuildableName = "TestChat.app"
BlueprintName = "TestChat"
ReferencedContainer = "container:SocketRocket.xcodeproj">
</BuildableReference>
</MacroExpansion>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "F62417E214D52F3C003CE997"
BuildableName = "TestChat.app"
BlueprintName = "TestChat"
ReferencedContainer = "container:SocketRocket.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
<AdditionalOption
<<<<<<< HEAD
=======
key = "NSZombieEnabled"
value = "YES"
isEnabled = "YES">
</AdditionalOption>
<AdditionalOption
>>>>>>> origin/master
key = "OBJC_PRINT_EXCEPTIONS"
value = "YES"
isEnabled = "YES">
</AdditionalOption>
<<<<<<< HEAD
=======
<AdditionalOption
key = "MallocGuardEdges"
value = ""
isEnabled = "YES">
</AdditionalOption>
<AdditionalOption
key = "MallocScribble"
value = ""
isEnabled = "YES">
</AdditionalOption>
>>>>>>> origin/master
</AdditionalOptions>
</LaunchAction>
<ProfileAction
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "F62417E214D52F3C003CE997"
BuildableName = "TestChat.app"
BlueprintName = "TestChat"
ReferencedContainer = "container:SocketRocket.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

32
SocketRocket/Common.h Normal file
View File

@ -0,0 +1,32 @@
//
// Common.h
// SocketRocket
//
// Created by Michael Lewis on 1/15/13.
//
//
#ifndef SocketRocket_Common_h
#define SocketRocket_Common_h
#ifdef __cplusplus
extern "C" {
#endif
#if OS_OBJECT_USE_OBJC_RETAIN_RELEASE
#define sr_dispatch_retain(x)
#define sr_dispatch_release(x)
#define __sr_maybe_bridge__ __bridge
#define __sr_maybe_strong__ __strong
#else
#define sr_dispatch_retain(x) dispatch_retain(x)
#define sr_dispatch_release(x) dispatch_release(x)
#define __sr_maybe_bridge__
#define __sr_maybe_strong__
#endif
#ifdef __cplusplus
}
#endif
#endif

149
SocketRocket/DispatchData.h Normal file
View File

@ -0,0 +1,149 @@
//
// DispatchData.h
// SocketRocket
//
// Created by Michael Lewis on 1/12/13.
//
//
#ifndef __SocketRocket__DispatchData__
#define __SocketRocket__DispatchData__
#include <string.h>
#include <iostream>
#include <dispatch/dispatch.h>
#include <deque>
#include "Common.h"
namespace squareup {
namespace dispatch {
class Data {
__sr_maybe_strong__ dispatch_data_t _data;
public:
inline Data() : Data(dispatch_data_empty) {
}
// Initializes a new data. retains the data by default
// Data always releases _data;
inline Data(dispatch_data_t data, bool retain = true) : _data(data) {
if (retain && _data) {
sr_dispatch_retain(_data);
}
}
// Will copy the data
inline Data(const char *str, dispatch_queue_t release_queue) :
_data(dispatch_data_create(reinterpret_cast<const void *>(str), strlen(str), release_queue, DISPATCH_DATA_DESTRUCTOR_DEFAULT)) {
}
// Copy constructor
inline Data(const Data &other) : Data(static_cast<dispatch_data_t>(other), true) {
}
inline Data(const void *bytes, size_t length, dispatch_queue_t release_queue) :
_data(dispatch_data_create(bytes, length, release_queue, DISPATCH_DATA_DESTRUCTOR_DEFAULT)) {
}
inline Data Concat(dispatch_data_t other) const {
return Data(dispatch_data_create_concat(_data, other), false);
}
inline Data operator + (dispatch_data_t other) const {
return Concat(other);
}
inline Data Subrange(size_t offset, size_t length) const {
return Data(dispatch_data_create_subrange(_data, offset, length), false);
}
// copies bytes into the buffer, and returns the remaining.
inline Data TakeInto(size_t length, void *bytes) const {
size_t size = Size();
assert(length <= size);
Apply([&](dispatch_data_t region, size_t offset, const void *buffer, size_t size) -> bool {
size_t numToCopy = std::min(size, length - offset);
memcpy(reinterpret_cast<void *>(reinterpret_cast<uint8_t *>(bytes) + offset), buffer, numToCopy);
return size + offset <= length;
});
if (length == size) {
return dispatch_data_empty;
}
return Subrange(length, size - length);
}
inline Data Map(const void **buffer_ptr, size_t *size_ptr) const {
return Data(dispatch_data_create_map(_data, buffer_ptr, size_ptr), false);
}
inline Data CopyRegion(size_t location, size_t *offset_ptr) const {
return Data(dispatch_data_copy_region(_data, location, offset_ptr), false);
}
inline bool Apply(dispatch_data_applier_t applier) const {
return dispatch_data_apply(_data, applier);
}
inline size_t Size() const {
return dispatch_data_get_size(static_cast<dispatch_data_t>(*this));
}
// This is a workaround since the memory gets quite fragmented if you use it as a stream
inline void FlattenIfNecessary() {
if (NumRegions() > 100) {
size_t size;
const void * buffer;
(*this) = Data(Map(&buffer, &size));
}
}
inline size_t NumRegions() {
size_t ret = 0;
Apply([&ret](dispatch_data_t region, size_t offset, const void *buffer, size_t size) -> bool {
ret += 1;
return true;
});
return ret;
}
inline operator dispatch_data_t() const {
return _data;
}
inline Data &operator = (const dispatch_data_t &other) {
if (other) {
sr_dispatch_retain(other);
}
if (_data) {
sr_dispatch_release(_data);
}
_data = other;
return *this;
}
inline Data &operator += (const Data &other) {
return (*this = Concat(other));
}
virtual ~Data() {
if (_data) {
sr_dispatch_release(_data);
}
}
static const Data empty;
};
}
}
#endif /* defined(__SocketRocket__DispatchData__) */

View File

@ -0,0 +1,15 @@
//
// DispatchData.cpp
// SocketRocket
//
// Created by Michael Lewis on 1/12/13.
//
//
#include "DispatchData.h"
namespace squareup {
namespace dispatch {
const Data Data::empty(dispatch_data_empty);
}
}

91
SocketRocket/DispatchIO.h Normal file
View File

@ -0,0 +1,91 @@
//
// DispatchChannel.h
// SocketRocket
//
// Created by Michael Lewis on 1/12/13.
//
//
#ifndef __SocketRocket__DispatchChannel__
#define __SocketRocket__DispatchChannel__
#include <dispatch/dispatch.h>
#include <string>
extern "C" {
#include <netdb.h>
}
namespace squareup {
namespace dispatch {
class RawIO;
typedef void (^dial_callback)(dispatch_fd_t fd, int error_code, const char *error_message);
void Dial(dispatch_queue_t workQueue, const char *hostname, const char *servname, dispatch_queue_t callback_queue, dial_callback callback);
// You are responsible for removing inputStream and outputStream
typedef void (^simple_dial_callback)(RawIO *io, int error, const char *error_message);
// callback_queue is what is sent to the clients but also
// parent_io_queue can be a parallel queue. the
// close_handler is passed to the RawIO
void SimpleDial(const char *hostname, const char *servname, dispatch_queue_t callback_queue, dispatch_queue_t parent_io_queue, simple_dial_callback dial_callback, void(^close_handler)(int error) = nullptr);
class IO {
public:
virtual void Close(dispatch_io_close_flags_t flags) = 0;
virtual void Read(size_t length, dispatch_queue_t queue, dispatch_io_handler_t handler) = 0;
virtual void Write(dispatch_data_t data, dispatch_queue_t queue, dispatch_io_handler_t handler) = 0;
virtual void Barrier(dispatch_block_t barrier) = 0;
virtual void SetHighWater(size_t high_water) = 0;
virtual void SetLowWater(size_t low_water) = 0;
virtual ~IO();
};
class RawIO : public IO {
dispatch_io_t _channel;
public:
void Close(dispatch_io_close_flags_t flags);
void Read(size_t length, dispatch_queue_t queue, dispatch_io_handler_t handler);
void Write(dispatch_data_t data, dispatch_queue_t queue, dispatch_io_handler_t handler);
void Barrier(dispatch_block_t barrier);
void SetHighWater(size_t high_water);
void SetLowWater(size_t low_water);
RawIO(dispatch_fd_t fd,
dispatch_queue_t cleanupQueue,
dispatch_queue_t callbackQueue,
dispatch_queue_t ioQueue,
void (^cleanup_handler)(int error));
// Takes ownership of channel
// retain is only for the channel
RawIO(dispatch_io_t channel,
dispatch_queue_t callbackQueue,
bool retain = true);
// Clones an existing IO
RawIO(dispatch_io_t otherIo,
dispatch_queue_t queue,
dispatch_queue_t callbackQueue,
dispatch_queue_t ioQueue,
void (^cleanup_handler)(int error));
inline operator dispatch_io_t () const {
return _channel;
}
virtual ~RawIO();
};
}
}
#endif /* defined(__SocketRocket__DispatchChannel__) */

298
SocketRocket/DispatchIO.mm Normal file
View File

@ -0,0 +1,298 @@
//
// DispatchChannel.cpp
// SocketRocket
//
// Created by Michael Lewis on 1/12/13.
//
//
#include "DispatchIO.h"
#include <Block.h>
#include <string>
#include "Common.h"
extern "C" {
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <errno.h>
}
// TODO: add deadlines
namespace squareup {
namespace dispatch {
IO::~IO() {};
class Connector;
typedef void(^finish_callback)(Connector *connector, addrinfo *res0, dispatch_fd_t fd, int error_code, const char *error_message);
class Connector {
addrinfo *_res;
addrinfo *_res0;
__strong finish_callback _finishCallback;
dispatch_queue_t _workQueue;
int _lastError;
const char *_lastErrorMessage;
bool _foundAddr = false;
public:
// Takes ownership of res0;
inline Connector(dispatch_queue_t workQueue, struct addrinfo *res0, finish_callback finishCallback) : _res(res0), _res0(res0), _finishCallback([finishCallback copy]), _workQueue(workQueue) {
sr_dispatch_retain(_workQueue);
}
virtual ~Connector() {
sr_dispatch_release(_workQueue);
}
inline void NextIter() {
_res = _res->ai_next;
dispatch_async(_workQueue, ^{
DoNext();
});
}
inline void DoNext() {
// We ran out of addresses
if (!_res) {
assert(!_foundAddr);
_finishCallback(this, _res0, -1, _lastError, _lastErrorMessage);
_finishCallback = nullptr;
return;
}
dispatch_fd_t fd = socket(_res->ai_family, _res->ai_socktype,
_res->ai_protocol);
if (fd < 0) {
_lastError = errno;
_lastErrorMessage = strerror(_lastError);
NextIter();
return;
}
int curflags = fcntl(fd, F_GETFL);
if (curflags < 0) {
_lastError = errno;
_lastErrorMessage = strerror(_lastError);
NextIter();
return;
}
// Set it to be nonblocking
int error = fcntl(fd, F_SETFL, curflags | O_NONBLOCK);
if (error) {
_lastError = errno;
_lastErrorMessage = strerror(_lastError);
NextIter();
return;
}
dispatch_source_t readSource = nullptr;
readSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, fd, 0, _workQueue);
dispatch_resume(readSource);
dispatch_source_set_event_handler(readSource, [this, fd, readSource]{
TryConnect(false, fd, readSource);
});
dispatch_source_set_cancel_handler(readSource, [fd]{
close(fd);
});
TryConnect(true, fd, readSource);
}
private:
// returns true if it is done
// if this is the first try we call connect. otherwise we check the status
inline void TryConnect(bool firstTry, dispatch_fd_t fd, dispatch_source_t readSource) {
// Now, set connection to be non-blocking
assert(!_foundAddr);
assert(fd != -1);
_lastError = 0;
if (firstTry) {
int error = connect(fd, _res->ai_addr, _res->ai_addrlen);
if (error != 0) {
_lastError = errno;
}
} else {
socklen_t len = sizeof(_lastError);
int sockErr = getsockopt(fd, SOL_SOCKET, SO_ERROR, &_lastError, &len);
assert(sockErr == 0);
}
if (_lastError != 0) {
if (_lastError != EINPROGRESS) {
_lastErrorMessage = strerror(_lastError);
dispatch_source_cancel(readSource);
sr_dispatch_release(readSource);
readSource = nullptr;
NextIter();
}
return;
}
_foundAddr = true;
// We don't want to close the FD, so make the cancel handler a noop
dispatch_suspend(readSource);
dispatch_source_set_cancel_handler(readSource, ^{});
dispatch_resume(readSource);
dispatch_source_cancel(readSource);
// Dispose of it without canceling it
sr_dispatch_release(readSource);
// Successful connections get here. Then we don't try anymore
// If we get this far, we're done
dispatch_async(_workQueue, [this, fd]{
_finishCallback(this, _res0, fd, 0, nullptr);
_finishCallback = nullptr;
});
return;
}
};
void Dial(dispatch_queue_t workQueue, const char *hostname, const char *servname, dispatch_queue_t callback_queue, dial_callback callback) {
callback = [callback copy];
sr_dispatch_retain(callback_queue);
// Does cleanup and whatnot
dispatch_async(workQueue, ^{
addrinfo *res0 = nullptr;
int error;
const char *cause = nullptr;
struct addrinfo hints = {0};
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo(hostname, servname, &hints, &res0);
auto finish = [callback_queue, callback, res0, workQueue](Connector *connector, addrinfo *res0, dispatch_fd_t fd, int error_code, const char *error_message){
NSLog(@"Pew");
dispatch_async(callback_queue, [fd, callback_queue, workQueue, error_message, callback, res0, connector, error_code]{
callback(fd, error_code, error_message);
if (res0) {
freeaddrinfo(res0);
}
if (connector) {
// Delete it after it doesn't reference this block anymore
dispatch_async(callback_queue, [workQueue, connector, callback_queue]{
delete connector;
sr_dispatch_release(callback_queue);
});
} else {
sr_dispatch_release(callback_queue);
}
});
};
if (error) {
cause = gai_strerror(error);
finish(nullptr, res0, -1, error, cause);
return;
}
Connector *connector = new Connector(workQueue, res0, finish);
connector->DoNext();
});
}
// callback_queue is what is sent to the clients but also
// parent_io_queue can be a parallel queue. the
void SimpleDial(const char *hostname, const char *servname, dispatch_queue_t callback_queue, dispatch_queue_t parent_io_queue, simple_dial_callback dial_callback, void (^close_handler)(int error)) {
dispatch_queue_t io_queue = dispatch_queue_create("squareup.dispatch.SimpleDial IO Queue", DISPATCH_QUEUE_SERIAL);
dispatch_set_target_queue(io_queue, parent_io_queue);
sr_dispatch_retain(callback_queue);
if (close_handler != nullptr) {
close_handler = [close_handler copy];
}
Dial(callback_queue, hostname, servname, callback_queue, [=](dispatch_fd_t fd, int error_code, const char *error_message) {
RawIO *io = nullptr;
if (error_code == 0) {
// Going to make the writer the primary.
// The write stream is also appropriate for closing
io = new RawIO(fd, callback_queue, callback_queue, io_queue, [fd, close_handler](int error) {
close(fd);
if (close_handler != nullptr) {
close_handler(error);
}
});
}
dial_callback(io, error_code, error_message);
sr_dispatch_release(io_queue);
sr_dispatch_release(parent_io_queue);
});
}
RawIO::RawIO(dispatch_fd_t fd,
dispatch_queue_t cleanupQueue,
dispatch_queue_t callbackQueue,
dispatch_queue_t ioQueue,
void (^cleanup_handler)(int error)) {
_channel = dispatch_io_create(DISPATCH_IO_STREAM, fd, cleanupQueue, cleanup_handler);
dispatch_set_target_queue(_channel, ioQueue);
}
// Takes ownership of channel
// retain is only for the channel
RawIO::RawIO(dispatch_io_t channel, dispatch_queue_t callbackQueue, bool retain) : _channel(channel) {
if (retain) {
sr_dispatch_retain(_channel);
}
};
// Clones an existing IO
RawIO::RawIO(dispatch_io_t otherIo, dispatch_queue_t queue, dispatch_queue_t callbackQueue, dispatch_queue_t ioQueue, void (^cleanup_handler)(int error)) :
RawIO(dispatch_io_create_with_io(DISPATCH_IO_STREAM, otherIo, queue, cleanup_handler), false) {
dispatch_set_target_queue(_channel, ioQueue);
}
RawIO::~RawIO() {
sr_dispatch_release(_channel);
_channel = nullptr;
}
void RawIO::Close(dispatch_io_close_flags_t flags) {
dispatch_io_close(_channel, flags);
}
void RawIO::Read(size_t length, dispatch_queue_t queue, dispatch_io_handler_t handler) {
dispatch_io_read(_channel, 0, length, queue, handler);
}
void RawIO::Write(dispatch_data_t data, dispatch_queue_t queue, dispatch_io_handler_t handler) {
dispatch_io_write(_channel, 0, data, queue, handler);
}
void RawIO::Barrier(dispatch_block_t barrier) {
dispatch_io_barrier(_channel, barrier);
}
void RawIO::SetHighWater(size_t high_water) {
dispatch_io_set_high_water(_channel, high_water);
}
void RawIO::SetLowWater(size_t low_water) {
dispatch_io_set_low_water(_channel, low_water);
}
}
}

View File

@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
extern "C" {
#import "SRWebSocket.h"
@ -34,20 +34,13 @@
#import <CommonCrypto/CommonDigest.h>
#import <Security/SecRandom.h>
#if OS_OBJECT_USE_OBJC_RETAIN_RELEASE
#define sr_dispatch_retain(x)
#define sr_dispatch_release(x)
#define maybe_bridge(x) ((__bridge void *) x)
#else
#define sr_dispatch_retain(x) dispatch_retain(x)
#define sr_dispatch_release(x) dispatch_release(x)
#define maybe_bridge(x) (x)
#endif
#import "Common.h"
#if !__has_feature(objc_arc)
#error SocketRocket must be compiled with ARC enabled
#endif
}
typedef enum {
SROpCodeTextFrame = 0x1,
@ -104,7 +97,7 @@ static inline void SRFastLog(NSString *format, ...);
@end
static NSString *newSHA1String(const char *bytes, size_t length) {
static NSString *newSHA1String(const void *bytes, size_t length) {
uint8_t md[CC_SHA1_DIGEST_LENGTH];
assert(length >= 0);
@ -305,7 +298,7 @@ static __strong NSData *CRLFCRLF;
_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
dispatch_queue_set_specific(_workQueue, (__bridge void *)self, maybe_bridge(_workQueue), NULL);
dispatch_queue_set_specific(_workQueue, (__bridge void *)self, (__sr_maybe_bridge__ void *)(_workQueue), NULL);
_delegateDispatchQueue = dispatch_get_main_queue();
sr_dispatch_retain(_delegateDispatchQueue);
@ -328,7 +321,7 @@ static __strong NSData *CRLFCRLF;
- (void)assertOnWorkQueue;
{
assert(dispatch_get_specific((__bridge void *)self) == maybe_bridge(_workQueue));
assert(dispatch_get_specific((__bridge void *)self) == (__sr_maybe_bridge__ void*)(_workQueue));
}
- (void)dealloc
@ -480,7 +473,7 @@ static __strong NSData *CRLFCRLF;
CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Host"), (__bridge CFStringRef)(_url.port ? [NSString stringWithFormat:@"%@:%@", _url.host, _url.port] : _url.host));
NSMutableData *keyBytes = [[NSMutableData alloc] initWithLength:16];
SecRandomCopyBytes(kSecRandomDefault, keyBytes.length, keyBytes.mutableBytes);
SecRandomCopyBytes(kSecRandomDefault, keyBytes.length, (uint8_t *)keyBytes.mutableBytes);
if ([keyBytes respondsToSelector:@selector(base64EncodedStringWithOptions:)]) {
_secKey = [keyBytes base64EncodedStringWithOptions:0];
@ -957,7 +950,7 @@ static const uint8_t SRPayloadLenMask = 0x7F;
[self _addConsumerWithDataLength:2 callback:^(SRWebSocket *self, NSData *data) {
__block frame_header header = {0};
const uint8_t *headerBuffer = data.bytes;
const uint8_t *headerBuffer = reinterpret_cast<const uint8_t *>(data.bytes);
assert(data.length >= 2);
if (headerBuffer[0] & SRRsvMask) {
@ -1054,7 +1047,7 @@ static const uint8_t SRPayloadLenMask = 0x7F;
NSUInteger dataLength = _outputBuffer.length;
if (dataLength - _outputBufferOffset > 0 && _outputStream.hasSpaceAvailable) {
NSInteger bytesWritten = [_outputStream write:_outputBuffer.bytes + _outputBufferOffset maxLength:dataLength - _outputBufferOffset];
NSInteger bytesWritten = [_outputStream write:reinterpret_cast<const uint8_t *>(_outputBuffer.bytes) + _outputBufferOffset maxLength:dataLength - _outputBufferOffset];
if (bytesWritten == -1) {
[self _failWithError:[NSError errorWithDomain:SRWebSocketErrorDomain code:2145 userInfo:[NSDictionary dictionaryWithObject:@"Error writing to stream" forKey:NSLocalizedDescriptionKey]]];
return;
@ -1063,7 +1056,7 @@ static const uint8_t SRPayloadLenMask = 0x7F;
_outputBufferOffset += bytesWritten;
if (_outputBufferOffset > 4096 && _outputBufferOffset > (_outputBuffer.length >> 1)) {
_outputBuffer = [[NSMutableData alloc] initWithBytes:(char *)_outputBuffer.bytes + _outputBufferOffset length:_outputBuffer.length - _outputBufferOffset];
_outputBuffer = [[NSMutableData alloc] initWithBytes:reinterpret_cast<const void *>(reinterpret_cast<const char *>(_outputBuffer.bytes) + _outputBufferOffset) length:_outputBuffer.length - _outputBufferOffset];
_outputBufferOffset = 0;
}
}
@ -1133,7 +1126,7 @@ static const char CRLFCRLFBytes[] = {'\r', '\n', '\r', '\n'};
__block size_t match_count = 0;
size_t size = data.length;
const unsigned char *buffer = data.bytes;
const uint8_t *buffer = reinterpret_cast<const uint8_t *>(data.bytes);
for (size_t i = 0; i < size; i++ ) {
if (((const unsigned char *)buffer)[i] == ((const unsigned char *)bytes)[match_count]) {
match_count += 1;
@ -1201,7 +1194,7 @@ static const char CRLFCRLFBytes[] = {'\r', '\n', '\r', '\n'};
NSMutableData *mutableSlice = [slice mutableCopy];
NSUInteger len = mutableSlice.length;
uint8_t *bytes = mutableSlice.mutableBytes;
uint8_t *bytes = reinterpret_cast<uint8_t *>(mutableSlice.mutableBytes);
for (NSUInteger i = 0; i < len; i++) {
bytes[i] = bytes[i] ^ _currentReadMaskKey[_currentReadMaskOffset % sizeof(_currentReadMaskKey)];

File diff suppressed because it is too large Load Diff

176
SocketRocket/SecureIO.h Normal file
View File

@ -0,0 +1,176 @@
//
// SecureIO.h
// SocketRocket
//
// Created by Michael Lewis on 1/12/13.
//
//
#ifndef __SocketRocket__SecureIO__
#define __SocketRocket__SecureIO__
#include "DispatchIO.h"
#include "DispatchData.h"
#include <deque>
#include <vector>
struct SSLContext;
namespace squareup {
namespace dispatch {
class SecureIO;
// You are responsible for removing inputStream and outputStream
typedef void (^dial_tls_callback)(SecureIO *io, int error, const char *error_message);
void DialTLS(const char *hostname, const char *servname, SSLContextRef ssl_context, dispatch_queue_t callback_queue, dispatch_queue_t work_queue, dispatch_queue_t parent_io_queue, dial_tls_callback dial_callback, void(^close_handler)(int error) = nullptr);
template <typename FuncType>
class QueuedHandle {
private:
__strong FuncType _handler = nullptr;
__sr_maybe_strong__ dispatch_queue_t _queue = nullptr;
public:
inline QueuedHandle() {
}
inline QueuedHandle(dispatch_queue_t queue, FuncType handler) {
_handler = [handler copy];
_queue = queue;
sr_dispatch_retain(_queue);
}
inline QueuedHandle(const QueuedHandle<FuncType> &other) : QueuedHandle(other._queue, other._handler){
}
inline QueuedHandle &operator=(const QueuedHandle &other){
_handler = other._handler;
_queue = other._queue;
sr_dispatch_release(_queue);
return *this;
}
inline ~QueuedHandle() {
if (_queue) {
sr_dispatch_release(_queue);
}
}
inline bool Valid() const {
return _handler != nullptr;
}
inline void Invalidate() {
_handler = nullptr;
}
template<typename... Args>
void operator () (Args... args) const {
assert(Valid());
FuncType handler = _handler;
dispatch_async(_queue, [handler, args...]{
handler(args...);
});
}
};
typedef QueuedHandle<dispatch_io_handler_t> DispatchHandler;
struct WriteJob {
bool isLast;
size_t rawBytes = 0;
size_t cryptedBytes = 0;
DispatchHandler handler;
};
struct ReadRequest {
// How many rawBytes we're expecting to read.
// This is populated in SSLRead.
size_t rawBytesRemaining = 0;
DispatchHandler handler;
};
class SecureIO : public IO {
IO *_io;
SSLContext *_context;
dispatch_queue_t _workQueue;
std::deque<WriteJob> _writeJobs;
std::deque<ReadRequest> _readRequests;
Data _waitingCryptedData;
size_t _cryptedBytesRequested = 0;
size_t _rawBytesRequested = 0;
size_t _highWater = SIZE_MAX;
size_t _lowWater = 1024 * 8;
bool _cancelled = false;
bool _closing = false;
// Set when we're inside of HandleSSLRead
// If we're reading and get a call to our SSLWriteHandler, the connection is probably being closed
bool _handlingRead = false;
// presence of this means handshake is in progress
DispatchHandler _handshakeHandler;
// This is set to true when we send a NULL data ptr. This is so we can request data we need.
bool _calculatingRequestSize = false;
std::vector<uint8_t> _sslReadBuffer;
public:
// Takes ownership of IO and delete it when done
SecureIO(IO *io, SSLContextRef context, dispatch_queue_t workQueue);
~SecureIO();
// This performs the handshake.
// There will be no data sent back to handler, but it will be called on completion
void Handshake(dispatch_queue_t queue, dispatch_io_handler_t handler);
void Close(dispatch_io_close_flags_t flags);
void Read(size_t length, dispatch_queue_t queue, dispatch_io_handler_t handler);
void Write(dispatch_data_t data, dispatch_queue_t queue, dispatch_io_handler_t handler);
void Barrier(dispatch_block_t barrier);
inline void SetHighWater(size_t high_water) {
_highWater = high_water;
}
void SetLowWater(size_t low_water) {
_lowWater = low_water;
}
private:
// Requests will ask the underlying stream for lenght - _rawBytesRequested
void RequestBytes(size_t length);
void Cancel(dispatch_io_close_flags_t flags, int error);
void CheckHandshake();
void InnerWrite(dispatch_data_t data, const DispatchHandler &handler);
// These really should be private
public:
OSStatus SSLReadHandler(void *data, size_t *dataLength);
OSStatus SSLWriteHandler(const void *data, size_t *dataLength);
private:
void HandleSSLWrite(bool done, size_t requestedLength, int error);
void HandleSSLRead(bool done, dispatch_data_t data, int error);
void PumpSSLRead();
void DoSSLRead();
};
}
}
#endif /* defined(__SocketRocket__SecureIO__) */

475
SocketRocket/SecureIO.mm Normal file
View File

@ -0,0 +1,475 @@
//
// SecureIO.cpp
// SocketRocket
//
// Created by Michael Lewis on 1/12/13.
//
//
#include <Security/SecureTransport.h>
#include "SecureIO.h"
#include "DispatchData.h"
#define ALLOW_INSECURE_SSL 1
namespace squareup {
namespace dispatch {
static OSStatus readFunc(SSLConnectionRef connection, void *data, size_t *dataLength);
static OSStatus writeFunc(SSLConnectionRef connection, const void *data, size_t *dataLength);
void DialTLS(const char *hostname,
const char *servname,
SSLContextRef ssl_context,
dispatch_queue_t callback_queue,
dispatch_queue_t work_queue,
dispatch_queue_t parent_io_queue,
dial_tls_callback dial_callback,
void(^close_handler)(int error)) {
if (close_handler != nullptr) {
close_handler = [close_handler copy];
}
dial_callback = [dial_callback copy];
sr_dispatch_retain(callback_queue);
// The work queue is the outer ones callback_queue
SimpleDial(hostname, servname, work_queue, parent_io_queue, [=](squareup::dispatch::RawIO *io, int error, const char *error_message) {
if (error != 0 || io == nullptr) {
dispatch_async(callback_queue, ^{
dial_callback(nullptr, error, error_message);
});
sr_dispatch_release(callback_queue);
return;
}
SecureIO *newIO = new SecureIO(io, ssl_context, work_queue);
sr_dispatch_release(callback_queue);
newIO->Handshake(callback_queue, [newIO, dial_callback](bool done, dispatch_data_t data, int error) {
SecureIO *io = newIO;
if (error) {
delete io;
io = nullptr;
}
// TODO: maybe add message?
dial_callback(io, error, nullptr);
});
}, close_handler);
}
SecureIO::SecureIO(IO *io, SSLContextRef context, dispatch_queue_t workQueue) :
_io(io), _context(context), _workQueue(workQueue) {
sr_dispatch_retain(_workQueue);
CFRetain(_context);
SSLSetConnection(_context, reinterpret_cast<const void *>(this));
SSLSetIOFuncs(_context, readFunc, writeFunc);
// TODO: delegate certificate authentication
#if ALLOW_INSECURE_SSL
SSLSetSessionOption(_context, kSSLSessionOptionBreakOnServerAuth, true);
#endif
}
SecureIO::~SecureIO() {
sr_dispatch_release(_workQueue);
CFRelease(_context);
// make sure things closed before we delete the io
assert(!_io);
}
void SecureIO::Handshake(dispatch_queue_t queue, dispatch_io_handler_t handler) {
_handshakeHandler = DispatchHandler(queue, handler);
dispatch_async(_workQueue, [this]{
CheckHandshake();
});
}
void SecureIO::Close(dispatch_io_close_flags_t flags) {
assert(!_closing);
dispatch_async(_workQueue, [this, flags]{
assert(!_closing);
_closing = true;
OSStatus status = SSLClose(_context);
// This shouldn't be a blocking operation
assert(status != errSSLWouldBlock);
Cancel(flags, status);
return;
});
}
void SecureIO::Read(size_t length, dispatch_queue_t queue, dispatch_io_handler_t handler) {
DispatchHandler dispatchHandler(queue, [handler copy]);
dispatch_async(_workQueue, [length, dispatchHandler, this]{
if (_cancelled) {
dispatchHandler(true, (dispatch_data_t)nullptr, ECANCELED);
return;
}
ReadRequest readRequest;
readRequest.handler = dispatchHandler;
readRequest.rawBytesRemaining += length;
_readRequests.push_back(readRequest);
// TODO: run on queue
_rawBytesRequested += length;
PumpSSLRead();
});
}
void SecureIO::PumpSSLRead() {
size_t buffSize = SIZE_MAX;
// This can happen if we have leftover data and haven't requested more.
while (buffSize > 0) {
// Make sure we are requesting enough;
OSStatus status = SSLGetBufferedReadSize(_context, &buffSize);
assert(status == 0);
if (buffSize > 0) {
if (_readRequests.size() == 0) {
return;
}
DoSSLRead();
}
}
_calculatingRequestSize = true;
const size_t maxBufferSize = 32 * 1024;
// We don't actually want to read anything into the _sslReadBuffer, howevr there's a bug when we go through 2g of data we have a memory issue
_sslReadBuffer.resize(std::max(_sslReadBuffer.capacity(), std::min(_rawBytesRequested, maxBufferSize)));
size_t dummyProcessed;
assert(buffSize == 0);
OSStatus status = ::SSLRead(_context, _sslReadBuffer.data(), _sslReadBuffer.size(), &dummyProcessed);
assert(dummyProcessed == 0);
_calculatingRequestSize = false;
if (status == errSSLClosedGraceful) {
if (!_closing) {
_closing = true;
Cancel(0, 0);
return;
}
}
assert(status == errSSLWouldBlock);
}
void SecureIO::Write(dispatch_data_t data, dispatch_queue_t queue, dispatch_io_handler_t handler) {
sr_dispatch_retain(data);
DispatchHandler dispatchHandler(queue, handler);
Data(data).Apply(^bool(dispatch_data_t region, size_t offset, const void *buffer, size_t size) {
return true;
});
dispatch_async(_workQueue, [data, dispatchHandler, this]{
InnerWrite(data, dispatchHandler);
sr_dispatch_release(data);
});
}
void SecureIO::InnerWrite(dispatch_data_t data, const DispatchHandler &handler) {
if (_cancelled) {
handler(true, (dispatch_data_t)nullptr, ECANCELED);
return;
}
OSStatus result = 0;
size_t totalSize = dispatch_data_get_size(data);
dispatch_data_apply(data, [&](dispatch_data_t region, size_t offset, const void *buffer, size_t size) -> bool {
WriteJob newJob;
newJob.handler = handler;
newJob.rawBytes = size;
newJob.isLast = offset + size == totalSize;
newJob.cryptedBytes = 0;
_writeJobs.push_back(newJob);
// WriteSSL will fill in the crypted bytes
// isLast will be set to True for the last one
size_t sizeWritten = 0;
result = ::SSLWrite(_context, buffer, size, &sizeWritten);
// I think we can make this assumption since we don't block at all in our handler.
if (result != 0) {
return false;
};
// We should be able to make this assumptions since our write func never blocks
assert(sizeWritten == size);
return true;
});
if (result) {
Cancel(0, result);
return;
}
}
void SecureIO::RequestBytes(size_t bytesWanted) {
if (bytesWanted > _cryptedBytesRequested) {
size_t requestSize = bytesWanted - _cryptedBytesRequested;
_cryptedBytesRequested += requestSize;
_io->Read(requestSize, _workQueue, [this](bool done, dispatch_data_t data, int error) {
HandleSSLRead(done, data, error);
});
}
};
OSStatus SecureIO::SSLReadHandler(void *data, size_t *dataLength) {
if (_calculatingRequestSize) {
RequestBytes(*dataLength);
*dataLength = 0;
return errSSLWouldBlock;
}
size_t bytesRequested = *dataLength;
// If _calculatingRequestSize is true, always return errSSLWouldBlock and pretend we don't have any data
size_t bytesToCopy = std::min(_waitingCryptedData.Size(), bytesRequested);
*dataLength = bytesToCopy;
if (bytesToCopy > 0) {
// Advance it forward
_waitingCryptedData = _waitingCryptedData.TakeInto(bytesToCopy, data);
_waitingCryptedData.FlattenIfNecessary();
}
if (bytesToCopy < bytesRequested) {
RequestBytes(bytesRequested - bytesToCopy);
return errSSLWouldBlock;
}
return noErr;
}
OSStatus SecureIO::SSLWriteHandler(const void *data, size_t *dataLength) {
size_t requestedLength = *dataLength;
if (!_handshakeHandler.Valid() && !_closing && !_handlingRead) {
assert(_writeJobs.size() > 0);
_writeJobs.back().cryptedBytes += requestedLength;
}
_io->Write(Data(data, requestedLength, _workQueue), _workQueue, [this, requestedLength](bool done, dispatch_data_t data, int error) {
HandleSSLWrite(done, requestedLength, error);
});
return 0;
}
void SecureIO::HandleSSLRead(bool done, dispatch_data_t data, int error) {
if (!_handshakeHandler.Valid() && _readRequests.size() == 0) {
return;
}
if (error != 0) {
if (_handshakeHandler.Valid()) {
_handshakeHandler(done, (dispatch_data_t)nullptr, error);
_handshakeHandler.Invalidate();
} else {
assert(_readRequests.size() > 0);
Cancel(0, error);
}
return;
}
// We got some data, so append it
Data d(data);
_cryptedBytesRequested -= d.Size();
_waitingCryptedData += d;
if (_handshakeHandler.Valid()) {
CheckHandshake();
return;
}
DoSSLRead();
PumpSSLRead();
}
void SecureIO::DoSSLRead() {
assert(_readRequests.size() > 0);
ReadRequest *frontRead = &_readRequests.front();
const DispatchHandler &handler = frontRead->handler;
size_t length = frontRead->rawBytesRemaining;
// Let's cap length at 2x the bytes we have available. probably won't use all of it (it will probably be less than 1x)
length = std::min(length, 2 * _waitingCryptedData.Size());
length = std::min(length, _highWater);
size_t buffSize = 0;
SSLGetBufferedReadSize(_context, &buffSize);
length = std::max(buffSize, length);
size_t sizeRead = 0;
void *buffer = malloc(length);
assert(buffer);
// TODO: optimize this and not malloc memory each time
assert(_calculatingRequestSize == false);
assert(_handlingRead == false);
_handlingRead = true;
OSStatus status = ::SSLRead(_context, buffer, length, &sizeRead);
_handlingRead = false;
if (status != 0 && status != errSSLWouldBlock && status != errSSLClosedGraceful) {
free(buffer);
buffer = nullptr;
// TODO: handle error better
Cancel(0, status);
return;
}
Data rawData(dispatch_data_create(buffer, sizeRead, _workQueue, DISPATCH_DATA_DESTRUCTOR_FREE), false);
frontRead->rawBytesRemaining -= sizeRead;
bool isDone = (frontRead->rawBytesRemaining == 0);
// TODO: honor watermarks
handler(isDone, rawData, 0);
if (status == errSSLClosedGraceful) {
// TODO: handle close
}
if (isDone) {
_readRequests.pop_front();
}
}
void SecureIO::HandleSSLWrite(bool done, size_t requestedLength, int error) {
if (_handshakeHandler.Valid()) {
CheckHandshake();
return;
}
if (_closing) {
return;
}
assert(_writeJobs.size() > 0);
// TODO(lewis): handle rest of errors better
if (error != 0) {
_writeJobs.front().handler(true, dispatch_data_empty, error);
return;
}
assert(_writeJobs.size());
// We only want to call the handlers when we are "done".
// This way we can approximate the bytes that are written
if (done) {
// if we're an error we want to go to the last one
if (error) {
Cancel(0, error);
return;
}
assert(_writeJobs.size());
_writeJobs.front().cryptedBytes -= requestedLength;
WriteJob writeJob = _writeJobs.front();
// Only call them when we're "done" for now, because we don't want to do bookkeeping of remaining data to consume
// TODO: probably change this
if (writeJob.cryptedBytes == 0) {
_writeJobs.pop_front();
if (writeJob.isLast) {
writeJob.handler(true, dispatch_data_empty, error);
}
}
}
}
void SecureIO::CheckHandshake() {
assert(_handshakeHandler.Valid());
OSStatus status = ::SSLHandshake(_context);
// If it would block we got nothing to do
if (status == errSSLWouldBlock) {
return;
}
#if ALLOW_INSECURE_SSL
// TODO: make this better
if (status == errSSLPeerAuthCompleted) {
CheckHandshake();
return;
}
#endif
_handshakeHandler(true, (dispatch_data_t)nullptr, status);
_handshakeHandler.Invalidate();
}
void SecureIO::Cancel(dispatch_io_close_flags_t flags, int error) {
_cancelled = true;
for (const ReadRequest &req : _readRequests) {
req.handler(true, (dispatch_data_t)nullptr, ECANCELED);
}
for (const WriteJob &job : _writeJobs) {
job.handler(true, (dispatch_data_t)nullptr, ECANCELED);
}
_readRequests.clear();
_writeJobs.clear();
_io->Close(flags);
delete _io;
_io = nullptr;
}
void SecureIO::Barrier(dispatch_block_t barrier) {
_io->Barrier(barrier);
}
OSStatus readFunc(SSLConnectionRef connection, void *data, size_t *dataLength) {
return reinterpret_cast<SecureIO *>((void *)connection)->SSLReadHandler(data, dataLength);
};
OSStatus writeFunc(SSLConnectionRef connection, const void *data, size_t *dataLength) {
return reinterpret_cast<SecureIO *>((void *)connection)->SSLWriteHandler(data, dataLength);
};
}
}

View File

@ -0,0 +1,142 @@
//
// Concurrent.swift
// SocketRocket
//
// Created by Mike Lewis on 8/7/15.
//
//
import Foundation
/// This is a nonblocking once. THis means that the once block
/// may fire after the callers that don't get it succeed
/// This is unlike the behavior of dispatch_once
struct Once {
var count: Int32 = 0
/// If this is the first one to call this, will invoke the block
///
/// :param: bit This structure can be used for more than one bit. We allow the first 16 bits to be used
///
/// :return: true if the block is ecuted
mutating func doMaybe(bit: Int = 0, block: () -> ()) -> Bool {
precondition(bit < 16)
guard !count.atomicTestAndSet(bit) else {
return false
}
block()
return true
}
}
extension Int32 {
mutating func atomicTestAndSet(bit: Int) -> Bool {
return withUnsafeMutablePointer(&self) { ptr in
return OSAtomicTestAndSet(UInt32(bit), ptr)
}
}
}
/// Building block for a
enum PState<V> {
case Pending
case Fulfilled(V)
case Rejected(ErrorType)
}
struct PGroup<T> {
/// TODO: remove locking somehow
typealias LockType = OSSpinLock
typealias Handler = (ErrorOptional<T>) -> ()
private var lock = LockType()
// These should only be mutated inside a lock
private var result: ErrorOptional<T>? = nil
// these are blocks enqueued while we don't have a result. Should be called when we actually fulfill
private var pendingHandlers = [Handler]()
var state = PState<T>.Pending
mutating func cancel() -> Bool {
return reject(Error.Canceled)
}
mutating func reject(e: ErrorType) -> Bool {
return fulfill(.Error(e))
}
mutating func fulfill(v: ErrorOptional<T>) -> Bool {
guard result == nil else {
return false
}
let blocksToRun: [Handler]? = lock.withLock() {
guard self.result == nil else {
return nil
}
self.result = v
let ret = self.pendingHandlers
self.pendingHandlers.removeAll()
return ret
}
guard let b = blocksToRun else {
return false
}
for bl in b {
bl(v)
}
return true
}
/// Adds a handler. Called immediately if result is set. Otherwise it will enqueue
mutating func then(h: Handler) -> Void {
// If we have a result, return it
if let v = self.result {
h(v)
return
}
let valueAgain: ErrorOptional<T>? = lock.withLock {
if let r = result {
return r
}
self.pendingHandlers.append(h)
return nil
}
if let v = valueAgain {
h(v)
}
}
init () {
}
private init(result: ErrorOptional<T>) {
self.result = result
}
static func resolve<T>(v: T) -> PGroup<T> {
return PGroup<T>(result: ErrorOptional<T>(v))
}
static func reject<T>(error: ErrorType) -> PGroup<T> {
return PGroup<T>(result: ErrorOptional<T>(error))
}
}

View File

@ -0,0 +1,49 @@
//
// Error.swift
// SocketRocket
//
// Created by Mike Lewis on 8/7/15.
//
//
/// Wraps errors. Has an uknown type if it cant resolve to an oserror
enum Error: ErrorType {
case Unknown(status: Int32)
case CodecError
case UTF8DecodeError
case Canceled
/// For functions that return negative value on error and expect errno to be set
static func checkReturnCode(returnCode: Int32) -> ErrorType? {
guard returnCode < 0 else {
return nil
}
return errorFromStatusCode(errno)
}
/// Returns an error type based on status code
static func errorFromStatusCode(status: Int32) -> ErrorType? {
guard status != 0 else {
return nil
}
if let e = POSIXError(rawValue: status) {
return e
}
return Error.Unknown(status: status)
}
static func throwIfNotSuccess(status: Int32) throws {
if let e = errorFromStatusCode(status) {
throw e
}
}
// Same as above, but checks if less than 0, and uses errno as the varaible
static func throwIfNotSuccessLessThan0(returnCode: Int32) throws {
if let e = checkReturnCode(returnCode) {
throw e
}
}
}

View File

@ -0,0 +1,71 @@
//
// ErrorOptional.swift
// SocketRocket
//
// Created by Mike Lewis on 8/3/15.
//
//
// Like optional but instead of None, it can take a nil
public enum ErrorOptional<T> {
case Error(ErrorType)
case Some(T)
/// Returns nil if ierrored. Using checkedGet is recommended
var orNil: T? {
get {
switch self {
case let Some(some):
return some
case Error:
return nil
}
}
}
var hasError: Bool {
get {
switch self {
case Some:
return false
case Error:
return true
}
}
}
func checkedGet() throws -> T {
switch self {
case let Some(some):
return some
case let Error(e):
throw e
}
}
/// Construct a non-`nil` instance that stores `some`.
init(_ some: T) {
self = Some(some)
}
init(_ error: ErrorType) {
self = Error(error)
}
// Will catch the first error and return with error wrapped in error optinal
static func attempt(block: () throws -> T) -> ErrorOptional<T> {
do {
return .Some(try block())
} catch let e {
return .Error(e)
}
}
}
public enum Errors: ErrorType {
case MultiError([ErrorType])
}

View File

@ -0,0 +1,44 @@
//
// Extensions.swift
// SocketRocket
//
// Created by Mike Lewis on 8/6/15.
//
//
import Dispatch
extension dispatch_data_t {
func apply(applier: UnsafeBufferPointer<UInt8> -> Bool) -> Bool {
return dispatch_data_apply(self) { (_, offset, buffer, size) -> Bool in
let mappedBuffer = unsafeBitCast(buffer, UnsafePointer<UInt8>.self)
let buffer = UnsafeBufferPointer(start: mappedBuffer.advancedBy(offset), count: size - offset)
return applier(buffer)
}
}
func apply(applier: UnsafeBufferPointer<UInt8> -> ()) -> Bool {
return self.apply { d -> Bool in
applier(d)
return true
}
}
func apply(applier: UnsafeBufferPointer<UInt8> throws -> ()) throws -> Bool {
var error: ErrorType? = nil
let ret = self.apply { d -> Bool in
do {
try applier(d)
return true
} catch let e {
error = e
return false
}
}
if let e = error {
throw e
}
return ret
}
}

319
SocketRocketIO/IO.swift Normal file
View File

@ -0,0 +1,319 @@
//
// IO.swift
// SocketRocket
//
// Created by Mike Lewis on 7/30/15.
//
//
import Foundation
import SystemShims
public struct CloseFlags : OptionSetType {
public init(rawValue: UInt) {
self.rawValue = rawValue
}
public let rawValue: UInt
public static let Stop = CloseFlags(rawValue: DISPATCH_IO_STOP)
}
public typealias DataHandler = (done: Bool, data: dispatch_data_t, error: ErrorType?) -> Void
public typealias ErrorHandler = (error: ErrorType?) -> Void
public protocol IO {
// Closes the IO. the callback will be called when finished. IO can only be closed once
// I/Os only exist once they're open.
func read(length: size_t, queue: Queue, handler: DataHandler)
func write(data: dispatch_data_t, queue: Queue, handler: DataHandler)
func close(queue: Queue, flags: CloseFlags)
}
public class RawIO: IO {
private let channel: dispatch_io_t
public init(channel: dispatch_io_t) {
self.channel = channel
}
public convenience init(fd: dispatch_fd_t,
cleanupQueue: Queue,
callbackQueue: Queue,
ioQueue: Queue,
cleanupHandler: ErrorHandler) {
let channel = dispatch_io_create(DISPATCH_IO_STREAM, fd, cleanupQueue.queue) { errorCode in
cleanupHandler(error: NSError.fromErrorCode(errorCode))
}
dispatch_set_target_queue(channel, ioQueue.queue);
self.init(channel: channel)
}
public func read(length: Int, queue: Queue, handler: DataHandler) {
dispatch_io_read(channel, 0, length, queue.queue, dataHandlerToIoHandler(handler))
}
public func write(data: dispatch_data_t, queue: Queue, handler: DataHandler) {
dispatch_io_write(channel, 0, data, queue.queue, dataHandlerToIoHandler(handler))
}
public func close(queue: Queue, flags: CloseFlags) {
dispatch_io_close(channel, flags.rawValue)
}
}
typealias IOFactory = (fd: dispatch_fd_t) -> IO
public class Listener {
let workQueue: Queue
let ioFactory: IOFactory
var eventSource: dispatch_source_t!
var closeHandler: ErrorHandler!
private init(workQueue: Queue, ioFactory: IOFactory) {
self.workQueue = workQueue
self.ioFactory = ioFactory
}
/// Starts listening
///
/// :param: queue queue callback is called on
/// :param: callback Called when listening starts. AN error if it failed
static func startListening(port: UInt16, address: String, workQueue: Queue, ioFactory: IOFactory, queue: Queue, callback: ErrorHandler) -> Listener {
let l = Listener(workQueue: workQueue, ioFactory: ioFactory)
return l
}
public func close(queue: Queue, handler: ErrorHandler) {
workQueue.dispatchAsync {
self.closeHandler = handler
dispatch_source_cancel(self.eventSource)
self.eventSource = nil
}
}
}
extension NSError {
convenience init(osError: Int32) {
self.init(domain: NSPOSIXErrorDomain, code: Int(osError), userInfo: nil)
}
static func fromErrorCode(osError: Int32) -> NSError? {
if osError == 0 {
return nil;
}
return NSError(osError: osError)
}
}
private func dataHandlerToIoHandler(handler: DataHandler) -> dispatch_io_handler_t {
return { done, data, errorCode in
handler(done: done, data: data, error: NSError.fromErrorCode(errorCode))
}
}
public protocol SockAddr {
init()
mutating func setup(listenAddr: Address, listenPort: UInt16) throws
static var size : Int {get}
static var addressFamily: Int32 { get }
}
public enum Address {
case Loopback
case Any
case IPV6Addr(address: String)
case IPV4Addr(address: String)
}
extension sockaddr_in6: SockAddr {
public mutating func setup(listenAddr: Address, listenPort: UInt16) throws {
switch listenAddr {
case .Any:
self.sin6_addr = in6addr_any
case let .IPV6Addr(address: address):
try Error.throwIfNotSuccess(inet_pton(self.dynamicType.addressFamily, address, &self.sin6_addr))
case .IPV4Addr:
fatalError("Cannot listen to IPV4Address in an ipv6 socket")
case .Loopback:
self.sin6_addr = in6addr_loopback
}
self.sin6_port = listenPort.bigEndian
self.sin6_family = sa_family_t(self.dynamicType.addressFamily)
self.sin6_len = UInt8(self.dynamicType.size)
}
public static let size = sizeof(sockaddr_in6)
public static let addressFamily = AF_INET6
}
let INADDR_ANY = in_addr(s_addr: 0x00000000)
let INADDR_LOOPBACK4 = in_addr(s_addr: UInt32(0x7f000001).bigEndian)
extension sockaddr_in: SockAddr {
public static let size = sizeof(sockaddr_in)
public static let addressFamily = AF_INET
public mutating func setup(listenAddr: Address, listenPort: UInt16) throws {
switch listenAddr {
case .Any:
self.sin_addr = INADDR_ANY
case let .IPV4Addr(address: address):
try Error.throwIfNotSuccess(inet_pton(self.dynamicType.addressFamily, address, &self.sin_addr))
case .IPV6Addr:
fatalError("Cannot listen to IPV6Address in an ipv4 socket")
case .Loopback:
self.sin_addr = INADDR_LOOPBACK4
}
self.sin_port = listenPort.bigEndian
self.sin_family = sa_family_t(self.dynamicType.addressFamily)
self.sin_len = UInt8(self.dynamicType.size)
}
}
extension SockAddr {
// func connect() {
// AF_INET
// }
}
let defaultBacklog: Int32 = 5
// Wrapper around a raw socket. Can do ipv6 or ipv4
public class Socket<T: SockAddr> {
var addr = T()
var fd: dispatch_fd_t = -1
// Initializes as a nonblocking socket and starts listening. DOes not create a dispatch source
public init(address: Address, port: UInt16) throws {
fd = socket(T.addressFamily, SOCK_STREAM, IPPROTO_TCP)
try Error.throwIfNotSuccessLessThan0(fd)
do {
let flags = shim_fcntl(fd, F_GETFL, 0);
try Error.throwIfNotSuccessLessThan0(shim_fcntl(fd, F_SETFL, flags | O_NONBLOCK))
var val: Int32 = 1;
try Error.throwIfNotSuccessLessThan0(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, socklen_t(sizeofValue(val))))
try Error.throwIfNotSuccessLessThan0(setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &val, socklen_t(sizeofValue(val))))
try addr.setup(address, listenPort: port)
try Error.throwIfNotSuccessLessThan0(shim_bind(fd, &addr, addr.dynamicType.size))
try Error.throwIfNotSuccessLessThan0(listen(fd, defaultBacklog))
} catch let e {
close(fd)
self.fd = -1
throw e
}
}
/// Cancel handler isn't guaranteed to dispatch on a specific queue
/// Returns a block that starts the cancel
public func startAccepting(workQueue: Queue, cancelHandler: () -> Void, acceptHandler:(fd: dispatch_fd_t) -> Void) -> (() -> Void) {
precondition(fd >= 0)
let eventSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, UInt(fd), 0, workQueue.queue)
dispatch_source_set_event_handler(eventSource) {
var remoteAddress = T()
var len = socklen_t(remoteAddress.dynamicType.size);
let native: dispatch_fd_t = shim_accept(self.fd, &remoteAddress, &len)
if native == -1 {
return;
}
acceptHandler(fd: native)
}
dispatch_source_set_cancel_handler(eventSource) {
precondition(self.fd >= 0)
close(self.fd);
self.fd = -1
cancelHandler()
}
dispatch_resume(eventSource);
return {
dispatch_source_cancel(eventSource)
}
}
}
extension dispatch_data_t {
var empty: Bool {
get {
return dispatch_data_empty === self
}
}
}
private var hints: addrinfo = {
var hints = addrinfo()
hints.ai_family = PF_UNSPEC
hints.ai_socktype = SOCK_STREAM
return hints
}()
extension Queue {
/// Used to dispatch synchronous operations on a specific queue
func blockingPromise<T>(blockingFn: () throws -> T) -> Promise<T> {
let (r, p) = Promise<T>.resolver()
self.dispatchAsync {
r.attemptResolve { return try blockingFn()}
}
return p
}
}
public func getaddrinfoAsync(hostname: String, servname: String, workQueue: Queue = Queue.defaultGlobalQueue) -> Promise<[addrinfo]> {
return workQueue.blockingPromise {
var ai: UnsafeMutablePointer<addrinfo> = nil
defer {
if ai != nil {
freeaddrinfo(ai)
}
}
// ai won't be set if it doesn't work
// TODO(lewis) propagate error up
try Error.throwIfNotSuccess(getaddrinfo(hostname, servname, &hints, &ai))
var ret = [addrinfo]()
var curAi = ai
while curAi != nil {
var mutatedAI = curAi.memory
let next = mutatedAI.ai_next
mutatedAI.ai_next = nil
ret.append(mutatedAI)
curAi = next
}
return ret;
}
}

26
SocketRocketIO/Info.plist Normal file
View File

@ -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>

34
SocketRocketIO/Lock.swift Normal file
View File

@ -0,0 +1,34 @@
//
// Lock.swift
// SocketRocket
//
// Created by Mike Lewis on 8/3/15.
//
//
protocol Lock {
mutating func lock()
mutating func unlock()
}
extension Lock {
mutating func withLock<Result>(@noescape fn: () throws -> Result) rethrows -> Result {
lock()
defer {
unlock()
}
return try fn()
}
}
extension OSSpinLock: Lock {
mutating func lock() {
withUnsafeMutablePointer(&self, OSSpinLockLock)
}
mutating func unlock() {
withUnsafeMutablePointer(&self, OSSpinLockUnlock)
}
}

View File

@ -0,0 +1,188 @@
//
// Promise.swift
// SocketRocket
//
// Created by Mike Lewis on 8/3/15.
//
//
import Foundation
// Only part of a promise protocol. It defines that it can be terminated
// Represents a return type that can either be a promise or a value
public enum PromiseOrValue<V> {
public typealias P = Promise<V>
case Promised(P)
case Value(P.ET)
static func of<V>(val: V) -> PromiseOrValue<V> {
return .Value(ErrorOptional<V>(val))
}
}
func wrap<T>(queue: Queue?, fn:(T) -> ()) -> (T) -> () {
if let q = queue {
return q.wrap(fn)
}
return fn
}
extension Queue {
/// wraps a void function and returns a new one. When
/// the new one is called it will be dispatched on the sender
func wrap<T>(fn:(T) -> ()) -> (T) -> () {
return { v in
self.dispatchAsync {
fn(v)
}
}
}
}
public struct Resolver<T> {
public typealias ET = ErrorOptional<T>
typealias P = Promise<T>
private let promise: P
init(promise: P) {
self.promise = promise
}
public func resolve(value: T) {
fulfill(ET(value))
}
public func reject(error: ErrorType) {
fulfill(ET(error))
}
/// resolves with the return value. Otherwise if it throws, it will return as an error type
public func attemptResolve(block: () throws -> T) {
fulfill(ET.attempt { return try block() })
}
public func fulfill(v: ET) {
promise.fulfill(v)
}
}
/// Useful for stuff that can only succeed and not return any errors
public typealias VoidPromiseType = Promise<Void>
public typealias VoidResolverType = Resolver<Void>
public class Promise<T> {
/// Error optional type
public typealias ET = ErrorOptional<T>
typealias PG = PGroup<T>
var pgroup: PG
typealias PV = PromiseOrValue<T>
typealias ValueType = T
private init(pgroup: PG) {
self.pgroup = pgroup
}
public class func resolve(value: T) -> Promise<T> {
return Promise<T>(pgroup: PGroup<T>.resolve(value))
}
public class func reject(error: ErrorType) -> Promise<T> {
return Promise<T>(pgroup: PGroup<T>.reject(error))
}
// Returns a promise and the resolver for it
public class func resolver() -> (Resolver<T>, Promise<T>) {
let p = Promise<T>()
let r = Resolver(promise: p)
return (r, p)
}
// An uninitialized one
init() {
pgroup = PG()
}
// splits the call based one rror or success
public func thenSplit<R>(queue: Queue? = nil, error: ((ErrorType) -> ())? = nil, success: T -> PromiseOrValue<R>) -> Promise<R> {
return self.then { (r:ET) -> PromiseOrValue<R> in
switch r {
case let .Error(e):
error?(e)
// TODO: improve this .Not very efficient
return PromiseOrValue.Value(Promise<R>.ET(e))
case let .Some(val):
return success(val)
}
}
}
public func then<R>(queue: Queue? = nil, handler: ET -> PromiseOrValue<R>) -> Promise<R> {
let (r, p) = Promise<R>.resolver()
self.then(queue) { v -> Void in
switch handler(v) {
case let .Promised(prom):
prom.then(handler: r.fulfill)
case let .Value(val):
r.fulfill(val)
}
}
return p
}
/// Terminating
func then(queue: Queue? = nil, handler: ET -> Void) {
self.pgroup.then(wrap(queue, fn: handler))
}
public func then<R>(queue: Queue? = nil, handler: ET -> Promise<R>.ET) -> Promise<R> {
let (r, p) = Promise<R>.resolver()
self.then(queue) { v -> Void in
r.fulfill(handler(v))
}
return p
}
/// Catches an error and propagates it in the optitional
///
/// Callers of this should use the .checkedGet on the input type to make it easy to propagate errors
///
/// Example:
///
/// p.thenChecked{ v throws in
/// return try v.checkedGet() + 3
/// }
public func thenChecked<R>(queue: Queue? = nil, handler: ET throws -> R) -> Promise<R> {
typealias RP = Promise<R>
typealias RET = RP.ET
return self.then(queue) { val -> ErrorOptional<R> in
do {
return RET(try handler(val))
} catch let e {
return RET(e)
}
}
}
private func fulfill(value: ET) {
pgroup.fulfill(value)
}
}

View File

@ -0,0 +1,58 @@
//
// Queue.swift
// SocketRocket
//
// Created by Mike Lewis on 7/30/15.
//
// Wrappers areound dispatch_queue_t
import Foundation
import Dispatch
/// Simple wrapper around dispatch_queue_t
public class Queue {
let queue: dispatch_queue_t
// used to check current queue
private var ctxKeyValue: UnsafeMutablePointer<Void> = nil
/// same as dispatch_get_main_queue()
public static let mainQueue = Queue(queue: dispatch_get_main_queue())
public static let defaultGlobalQueue = Queue(queue: dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0))
public required init(queue: dispatch_queue_t) {
self.queue = queue
withUnsafeMutablePointer(&self.ctxKeyValue) { ptr in
self.ctxKeyValue = unsafeBitCast(ptr, UnsafeMutablePointer<Void>.self);
}
let destructor: dispatch_function_t! = nil
dispatch_queue_set_specific(self.queue, ctxKeyValue, ctxKeyValue, destructor)
}
public convenience init(label: String, attr: dispatch_queue_attr_t? = DISPATCH_QUEUE_SERIAL) {
self.init(queue: dispatch_queue_create(label, attr))
}
deinit {
let destructor: dispatch_function_t! = nil
dispatch_queue_set_specific(self.queue, ctxKeyValue, nil, destructor)
}
public func dispatchAsync(block: () -> Void) {
dispatch_async(queue, block)
}
/// Returns true if we're on the current queue
public func isCurrentQueue() -> Bool {
let currentContext = dispatch_get_specific(ctxKeyValue)
return currentContext == ctxKeyValue
}
public func checkIsCurrentQueue() {
precondition(isCurrentQueue(), "Expected to be current queue")
}
}

View File

@ -0,0 +1,18 @@
//
// SocketRocketIO.h
// SocketRocketIO
//
// Created by Mike Lewis on 7/30/15.
//
//
#import <Foundation/Foundation.h>
//! Project version number for SocketRocketIO.
FOUNDATION_EXPORT double SocketRocketIOVersionNumber;
//! Project version string for SocketRocketIO.
FOUNDATION_EXPORT const unsigned char SocketRocketIOVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <SocketRocketIO/PublicHeader.h>

View File

@ -0,0 +1,168 @@
//
// Unicode.swift
// SocketRocket
//
// Created by Mike Lewis on 8/6/15.
//
//
extension UTF8 {
/// Returns number of code units. Throws if its not the first bite of a unicode charactser
/// result includes selve
static func numCodeUnits(first: CodeUnit) throws -> Int {
guard first & 0b1100_0000 != 0b1000_0000 else {
throw Error.UTF8DecodeError
}
// If the first bit is 0, its a single code-point
if first & 0b1000_0000 == 0b0000_0000 {
return 1
}
if first & 0b1110_0000 == 0b1100_0000 {
return 2
}
if first & 0b1111_0000 == 0b1110_0000 {
return 3
}
if first & 0b1111_1000 == 0b1111_0000 {
return 4
}
throw Error.UTF8DecodeError
}
/// Returns the number of valid codeunits from the generator
static func numValidCodeUnits<G: GeneratorType where G.Element == CodeUnit>(var g: G) throws -> Int {
var numValidCodeUnits = 0
outOfCharacters:
for var c = g.next(); c != nil; c = g.next() {
let numCodeUnits = try UTF8.numCodeUnits(c!)
for _ in 0..<(numCodeUnits - 1) {
if let c = g.next() {
guard UTF8.isContinuation(c) else {
throw Error.UTF8DecodeError
}
} else {
break outOfCharacters
}
}
numValidCodeUnits += numCodeUnits
}
return numValidCodeUnits
}
}
struct RawUTF8Codec<CT: CollectionType, GT: GeneratorType where CT.Generator == GT, GT.Element == UInt8, CT.Index.Distance == Int, CT.Index: RandomAccessIndexType, CT.Generator.Element == UInt8, CT.SubSequence.Generator.Element == UInt8> : Codec {
typealias InType = CT
typealias OutType = String.UnicodeScalarView
typealias CodeUnit = UInt8
typealias UnicodeCodec = UTF8
var outputBuffer = String()
/// Used to buffer unfinished UTF8 Sequences
var inputBuffer = [CodeUnit]()
/// Consumes to our outputbuffer
mutating func consume<G: GeneratorType where G.Element == CodeUnit>(var g: G) throws {
var uc = UTF8()
while true {
switch uc.decode(&g) {
case .EmptyInput:
return
case .Error:
throw Error.UTF8DecodeError
case let .Result(scalar):
outputBuffer.append(scalar)
}
}
}
mutating func code(input: ValueOrEnd<AnyRandomAccessCollection<InType.Generator.Element>>) throws -> OutType {
defer {
outputBuffer.removeAll(keepCapacity: true)
}
switch input {
case .End:
if inputBuffer.isEmpty {
return "".unicodeScalars
} else {
throw Error.UTF8DecodeError
}
case let .Value(v):
let totalSize = inputBuffer.count + v.count
outputBuffer.reserveCapacity(Int(totalSize))
let numValidCodeUnits = try UTF8.numValidCodeUnits(inputBuffer.generate() + v.generate())
let numUnfinished = totalSize - numValidCodeUnits
// If this happens, we didn't get enough for even one character
if numUnfinished == totalSize {
inputBuffer += v
return "".unicodeScalars
}
if numUnfinished > 0 {
let truncatedG = v[v.startIndex..<v.endIndex.advancedBy(-numUnfinished)].generate()
let g = inputBuffer.generate() + truncatedG
try consume(g)
} else {
try consume(inputBuffer.generate() + v.generate())
}
inputBuffer.removeAll(keepCapacity: true)
if numUnfinished > 0 {
inputBuffer += v[v.endIndex.advancedBy(-numUnfinished)..<v.endIndex]
}
return outputBuffer.unicodeScalars
}
}
}
extension DispatchIO: AsyncReadable {
typealias Collection = UnsafeBufferPointer<UInt8>
func read(size: Collection.Index.Distance, queue: Queue, handler: (AnyRandomAccessCollection<Collection.Generator.Element>) throws -> ()) -> VoidPromiseType {
let (r, p) = VoidPromiseType.resolver()
dispatch_io_read(io, 0, size, queue.queue) { finished, data, error in
guard error == 0 else {
r.reject(Error.errorFromStatusCode(error)!)
return
}
do {
try data.apply { d in
try handler(AnyRandomAccessCollection(d))
}
} catch let e {
// TODO(don't double-call this error)
r.reject(e)
return
}
if finished {
r.resolve(Void())
}
}
return p
}
}

View File

@ -0,0 +1,135 @@
//
// ConcurrentTests.swift
// SocketRocket
//
// Created by Mike Lewis on 8/7/15.
//
//
@testable import SocketRocketIO
import XCTest
class ConcurrentTests: XCTestCase {
func testOnce_simple() {
var once = Once()
let e2 = expectationWithDescription("All done")
let g = dispatch_group_create()
let g2 = dispatch_group_create()
dispatch_group_enter(g)
dispatch_group_notify(g2, Queue.defaultGlobalQueue.queue) {
e2.fulfill()
}
for bit in 0..<8 {
let e = expectationWithDescription("Once filled")
for _ in 0..<1000 {
dispatch_group_enter(g2)
dispatch_group_notify(g, Queue.defaultGlobalQueue.queue) {
once.doMaybe(bit, block: {
e.fulfill()
})
dispatch_group_leave(g2)
}
}
}
dispatch_group_leave(g)
waitForExpectations()
}
func testPerformanceExample() {
// This is an example of a performance test case.
self.measureBlock {
// Put the code you want to measure the time of here.
}
}
func testPGroup_noerr() {
var p = PGroup<Int>()
p.fulfill(ErrorOptional(3))
for i in 0..<20 {
let e = self.expectationWithDescription("e \(i)")
p.then { v in
XCTAssertFalse(v.hasError)
e.fulfill()
}
}
self.waitForExpectations()
}
func testPGroup_after() {
var p = PGroup<Int>()
for i in 0..<20 {
let e = self.expectationWithDescription("e \(i)")
p.then { v in
XCTAssertFalse(v.hasError)
e.fulfill()
switch v {
case let .Some(val):
XCTAssertEqual(val, 3)
default:
XCTFail()
}
}
}
p.fulfill(ErrorOptional(3))
self.waitForExpectations()
}
func testPGroup_calledOnce() {
var p = PGroup<Int>()
for i in 0..<20 {
let e = self.expectationWithDescription("e \(i)")
p.then { v in
switch v {
case let .Some(val):
XCTAssertEqual(val, 3)
default:
XCTFail()
}
e.fulfill()
}
}
p.fulfill(ErrorOptional(3))
p.fulfill(ErrorOptional(4))
p.fulfill(ErrorOptional(Error.Canceled))
self.waitForExpectations()
}
func testPGroup_canceled() {
var p = PGroup<Int>()
for i in 0..<20 {
let e = self.expectationWithDescription("e \(i)")
p.then { v in
switch v {
case .Error(Error.Canceled):
break
default:
XCTFail()
}
e.fulfill()
}
}
p.cancel()
p.fulfill(ErrorOptional(3))
p.fulfill(ErrorOptional(4))
p.fulfill(ErrorOptional(Error.Canceled))
self.waitForExpectations()
}
}

View File

@ -0,0 +1,5 @@
hello
this
is a file
I like to read from it

View File

@ -0,0 +1,212 @@
UTF-8 encoded sample plain-text file
‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
Markus Kuhn [ˈmaʳkʊs kuːn] <http://www.cl.cam.ac.uk/~mgk25/> — 2002-07-25
The ASCII compatible UTF-8 encoding used in this plain-text file
is defined in Unicode, ISO 10646-1, and RFC 2279.
Using Unicode/UTF-8, you can write in emails and source code things such as
Mathematics and sciences:
∮ E⋅da = Q, n → ∞, ∑ f(i) = ∏ g(i), ⎧⎡⎛┌─────┐⎞⎤⎫
⎪⎢⎜│a²+b³ ⎟⎥⎪
∀x∈: ⌈x⌉ = x⌋, α ∧ ¬β = ¬(¬α β), ⎪⎢⎜│───── ⎟⎥⎪
⎪⎢⎜⎷ c₈ ⎟⎥⎪
⊆ ℕ₀ ⊂ , ⎨⎢⎜ ⎟⎥⎬
⎪⎢⎜ ∞ ⎟⎥⎪
⊥ < a ≠ b ≡ c ≤ d ≪ ⇒ (⟦A⟧ ⇔ ⟪B⟫), ⎪⎢⎜ ⎲ ⎟⎥⎪
⎪⎢⎜ ⎳aⁱ-bⁱ⎟⎥⎪
2H₂ + O₂ ⇌ 2H₂O, R = 4.7 kΩ, ⌀ 200 mm ⎩⎣⎝i=1 ⎠⎦⎭
Linguistics and dictionaries:
ði ıntəˈnæʃənəl fəˈnɛtık əsoʊsiˈeıʃn
Y [ˈʏpsilɔn], Yen [jɛn], Yoga [ˈjoːgɑ]
APL:
((VV)=V)/V←,V ⌷←⍳→⍴∆∇⊃‾⍎⍕⌈
Nicer typography in plain text files:
╔══════════════════════════════════════════╗
║ ║
║ • single and “double” quotes ║
║ ║
║ • Curly apostrophes: “Weve been here” ║
║ ║
║ • Latin-1 apostrophe and accents: '´` ║
║ ║
║ • deutsche „Anführungszeichen“ ║
║ ║
║ • †, ‡, ‰, •, 34, —, 5/+5, ™, … ║
║ ║
║ • ASCII safety test: 1lI|, 0OD, 8B ║
║ ╭─────────╮ ║
║ • the euro symbol: │ 14.95 € │ ║
║ ╰─────────╯ ║
╚══════════════════════════════════════════╝
Combining characters:
STARGΛ̊TE SG-1, a = v̇ = r̈, a⃑ ⊥ b⃑
Greek (in Polytonic):
The Greek anthem:
Σὲ γνωρίζω ἀπὸ τὴν κόψη
τοῦ σπαθιοῦ τὴν τρομερή,
σὲ γνωρίζω ἀπὸ τὴν ὄψη
ποὺ μὲ βία μετράει τὴ γῆ.
᾿Απ᾿ τὰ κόκκαλα βγαλμένη
τῶν ῾Ελλήνων τὰ ἱερά
καὶ σὰν πρῶτα ἀνδρειωμένη
χαῖρε, ὦ χαῖρε, ᾿Ελευθεριά!
From a speech of Demosthenes in the 4th century BC:
Οὐχὶ ταὐτὰ παρίσταταί μοι γιγνώσκειν, ὦ ἄνδρες ᾿Αθηναῖοι,
ὅταν τ᾿ εἰς τὰ πράγματα ἀποβλέψω καὶ ὅταν πρὸς τοὺς
λόγους οὓς ἀκούω· τοὺς μὲν γὰρ λόγους περὶ τοῦ
τιμωρήσασθαι Φίλιππον ὁρῶ γιγνομένους, τὰ δὲ πράγματ᾿
εἰς τοῦτο προήκοντα, ὥσθ᾿ ὅπως μὴ πεισόμεθ᾿ αὐτοὶ
πρότερον κακῶς σκέψασθαι δέον. οὐδέν οὖν ἄλλο μοι δοκοῦσιν
οἱ τὰ τοιαῦτα λέγοντες ἢ τὴν ὑπόθεσιν, περὶ ἧς βουλεύεσθαι,
οὐχὶ τὴν οὖσαν παριστάντες ὑμῖν ἁμαρτάνειν. ἐγὼ δέ, ὅτι μέν
ποτ᾿ ἐξῆν τῇ πόλει καὶ τὰ αὑτῆς ἔχειν ἀσφαλῶς καὶ Φίλιππον
τιμωρήσασθαι, καὶ μάλ᾿ ἀκριβῶς οἶδα· ἐπ᾿ ἐμοῦ γάρ, οὐ πάλαι
γέγονεν ταῦτ᾿ ἀμφότερα· νῦν μέντοι πέπεισμαι τοῦθ᾿ ἱκανὸν
προλαβεῖν ἡμῖν εἶναι τὴν πρώτην, ὅπως τοὺς συμμάχους
σώσομεν. ἐὰν γὰρ τοῦτο βεβαίως ὑπάρξῃ, τότε καὶ περὶ τοῦ
τίνα τιμωρήσεταί τις καὶ ὃν τρόπον ἐξέσται σκοπεῖν· πρὶν δὲ
τὴν ἀρχὴν ὀρθῶς ὑποθέσθαι, μάταιον ἡγοῦμαι περὶ τῆς
τελευτῆς ὁντινοῦν ποιεῖσθαι λόγον.
Δημοσθένους, Γ´ ᾿Ολυνθιακὸς
Georgian:
From a Unicode conference invitation:
გთხოვთ ახლავე გაიაროთ რეგისტრაცია Unicode-ის მეათე საერთაშორისო
კონფერენციაზე დასასწრებად, რომელიც გაიმართება 10-12 მარტს,
ქ. მაინცში, გერმანიაში. კონფერენცია შეჰკრებს ერთად მსოფლიოს
ექსპერტებს ისეთ დარგებში როგორიცაა ინტერნეტი და Unicode-ი,
ინტერნაციონალიზაცია და ლოკალიზაცია, Unicode-ის გამოყენება
ოპერაციულ სისტემებსა, და გამოყენებით პროგრამებში, შრიფტებში,
ტექსტების დამუშავებასა და მრავალენოვან კომპიუტერულ სისტემებში.
Russian:
From a Unicode conference invitation:
Зарегистрируйтесь сейчас на Десятую Международную Конференцию по
Unicode, которая состоится 10-12 марта 1997 года в Майнце в Германии.
Конференция соберет широкий круг экспертов по вопросам глобального
Интернета и Unicode, локализации и интернационализации, воплощению и
применению Unicode в различных операционных системах и программных
приложениях, шрифтах, верстке и многоязычных компьютерных системах.
Thai (UCS Level 2):
Excerpt from a poetry on The Romance of The Three Kingdoms (a Chinese
classic 'San Gua'):
[----------------------------|------------------------]
๏ แผ่นดินฮั่นเสื่อมโทรมแสนสังเวช พระปกเกศกองบู๊กู้ขึ้นใหม่
สิบสองกษัตริย์ก่อนหน้าแลถัดไป สององค์ไซร้โง่เขลาเบาปัญญา
ทรงนับถือขันทีเป็นที่พึ่ง บ้านเมืองจึงวิปริตเป็นนักหนา
โฮจิ๋นเรียกทัพทั่วหัวเมืองมา หมายจะฆ่ามดชั่วตัวสำคัญ
เหมือนขับไสไล่เสือจากเคหา รับหมาป่าเข้ามาเลยอาสัญ
ฝ่ายอ้องอุ้นยุแยกให้แตกกัน ใช้สาวนั้นเป็นชนวนชื่นชวนใจ
พลันลิฉุยกุยกีกลับก่อเหตุ ช่างอาเพศจริงหนาฟ้าร้องไห้
ต้องรบราฆ่าฟันจนบรรลัย ฤๅหาใครค้ำชูกู้บรรลังก์ ฯ
(The above is a two-column text. If combining characters are handled
correctly, the lines of the second column should be aligned with the
| character above.)
Ethiopian:
Proverbs in the Amharic language:
ሰማይ አይታረስ ንጉሥ አይከሰስ።
ብላ ካለኝ እንደአባቴ በቆመጠኝ።
ጌጥ ያለቤቱ ቁምጥና ነው።
ደሀ በሕልሙ ቅቤ ባይጠጣ ንጣት በገደለው።
የአፍ ወለምታ በቅቤ አይታሽም።
አይጥ በበላ ዳዋ ተመታ።
ሲተረጉሙ ይደረግሙ።
ቀስ በቀስ፥ ዕንቁላል በእግሩ ይሄዳል።
ድር ቢያብር አንበሳ ያስር።
ሰው እንደቤቱ እንጅ እንደ ጉረቤቱ አይተዳደርም።
እግዜር የከፈተውን ጉሮሮ ሳይዘጋው አይድርም።
የጎረቤት ሌባ፥ ቢያዩት ይስቅ ባያዩት ያጠልቅ።
ሥራ ከመፍታት ልጄን ላፋታት።
ዓባይ ማደሪያ የለው፥ ግንድ ይዞ ይዞራል።
የእስላም አገሩ መካ የአሞራ አገሩ ዋርካ።
ተንጋሎ ቢተፉ ተመልሶ ባፉ።
ወዳጅህ ማር ቢሆን ጨርስህ አትላሰው።
እግርህን በፍራሽህ ልክ ዘርጋ።
Runes:
ᚻᛖ ᚳᚹᚫᚦ ᚦᚫᛏ ᚻᛖ ᛒᚢᛞᛖ ᚩᚾ ᚦᚫᛗ ᛚᚪᚾᛞᛖ ᚾᚩᚱᚦᚹᛖᚪᚱᛞᚢᛗ ᚹᛁᚦ ᚦᚪ ᚹᛖᛥᚫ
(Old English, which transcribed into Latin reads 'He cwaeth that he
bude thaem lande northweardum with tha Westsae.' and means 'He said
that he lived in the northern land near the Western Sea.')
Braille:
⡌⠁⠧⠑ ⠼⠁⠒ ⡍⠜⠇⠑⠹⠰⠎ ⡣⠕⠌
⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠙⠑⠁⠙⠒ ⠞⠕ ⠃⠑⠛⠔ ⠺⠊⠹⠲ ⡹⠻⠑ ⠊⠎ ⠝⠕ ⠙⠳⠃⠞
⠱⠁⠞⠑⠧⠻ ⠁⠃⠳⠞ ⠹⠁⠞⠲ ⡹⠑ ⠗⠑⠛⠊⠌⠻ ⠕⠋ ⠙⠊⠎ ⠃⠥⠗⠊⠁⠇ ⠺⠁⠎
⠎⠊⠛⠝⠫ ⠃⠹ ⠹⠑ ⠊⠇⠻⠛⠹⠍⠁⠝⠂ ⠹⠑ ⠊⠇⠻⠅⠂ ⠹⠑ ⠥⠝⠙⠻⠞⠁⠅⠻⠂
⠁⠝⠙ ⠹⠑ ⠡⠊⠑⠋ ⠍⠳⠗⠝⠻⠲ ⡎⠊⠗⠕⠕⠛⠑ ⠎⠊⠛⠝⠫ ⠊⠞⠲ ⡁⠝⠙
⡎⠊⠗⠕⠕⠛⠑⠰⠎ ⠝⠁⠍⠑ ⠺⠁⠎ ⠛⠕⠕⠙ ⠥⠏⠕⠝ ⠰⡡⠁⠝⠛⠑⠂ ⠋⠕⠗ ⠁⠝⠹⠹⠔⠛ ⠙⠑
⠡⠕⠎⠑ ⠞⠕ ⠏⠥⠞ ⠙⠊⠎ ⠙⠁⠝⠙ ⠞⠕⠲
⡕⠇⠙ ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠁⠎ ⠙⠑⠁⠙ ⠁⠎ ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲
⡍⠔⠙⠖ ⡊ ⠙⠕⠝⠰⠞ ⠍⠑⠁⠝ ⠞⠕ ⠎⠁⠹ ⠹⠁⠞ ⡊ ⠅⠝⠪⠂ ⠕⠋ ⠍⠹
⠪⠝ ⠅⠝⠪⠇⠫⠛⠑⠂ ⠱⠁⠞ ⠹⠻⠑ ⠊⠎ ⠏⠜⠞⠊⠊⠥⠇⠜⠇⠹ ⠙⠑⠁⠙ ⠁⠃⠳⠞
⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲ ⡊ ⠍⠊⠣⠞ ⠙⠁⠧⠑ ⠃⠑⠲ ⠔⠊⠇⠔⠫⠂ ⠍⠹⠎⠑⠇⠋⠂ ⠞⠕
⠗⠑⠛⠜⠙ ⠁ ⠊⠕⠋⠋⠔⠤⠝⠁⠊⠇ ⠁⠎ ⠹⠑ ⠙⠑⠁⠙⠑⠌ ⠏⠊⠑⠊⠑ ⠕⠋ ⠊⠗⠕⠝⠍⠕⠝⠛⠻⠹
⠔ ⠹⠑ ⠞⠗⠁⠙⠑⠲ ⡃⠥⠞ ⠹⠑ ⠺⠊⠎⠙⠕⠍ ⠕⠋ ⠳⠗ ⠁⠝⠊⠑⠌⠕⠗⠎
⠊⠎ ⠔ ⠹⠑ ⠎⠊⠍⠊⠇⠑⠆ ⠁⠝⠙ ⠍⠹ ⠥⠝⠙⠁⠇⠇⠪⠫ ⠙⠁⠝⠙⠎
⠩⠁⠇⠇ ⠝⠕⠞ ⠙⠊⠌⠥⠗⠃ ⠊⠞⠂ ⠕⠗ ⠹⠑ ⡊⠳⠝⠞⠗⠹⠰⠎ ⠙⠕⠝⠑ ⠋⠕⠗⠲ ⡹⠳
⠺⠊⠇⠇ ⠹⠻⠑⠋⠕⠗⠑ ⠏⠻⠍⠊⠞ ⠍⠑ ⠞⠕ ⠗⠑⠏⠑⠁⠞⠂ ⠑⠍⠏⠙⠁⠞⠊⠊⠁⠇⠇⠹⠂ ⠹⠁⠞
⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠁⠎ ⠙⠑⠁⠙ ⠁⠎ ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲
(The first couple of paragraphs of "A Christmas Carol" by Dickens)
Compact font selection example text:
ABCDEFGHIJKLMNOPQRSTUVWXYZ /0123456789
abcdefghijklmnopqrstuvwxyz £©µÀÆÖÞßéöÿ
–—‘“”„†•…‰™œŠŸž€ ΑΒΓΔΩαβγδω АБВГДабвгд
∀∂∈ℝ∧∪≡∞ ↑↗↨↻⇣ ┐┼╔╘░►☺♀ fi<>⑀₂ἠḂӥẄɐː⍎אԱა
Greetings in various languages:
Hello world, Καλημέρα κόσμε, コンニチハ
Box drawing alignment tests: █
╔══╦══╗ ┌──┬──┐ ╭──┬──╮ ╭──┬──╮ ┏━━┳━━┓ ┎┒┏┑ ╷ ╻ ┏┯┓ ┌┰┐ ▊ ╱╲╱╲╳╳╳
║┌─╨─┐║ │╔═╧═╗│ │╒═╪═╕│ │╓─╁─╖│ ┃┌─╂─┐┃ ┗╃╄┙ ╶┼╴╺╋╸┠┼┨ ┝╋┥ ▋ ╲╱╲╱╳╳╳
║│╲ ╱│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╿ │┃ ┍╅╆┓ ╵ ╹ ┗┷┛ └┸┘ ▌ ╱╲╱╲╳╳╳
╠╡ ╞╣ ├╢ ╟┤ ├┼─┼─┼┤ ├╫─╂─╫┤ ┣┿╾┼╼┿┫ ┕┛┖┚ ┌┄┄┐ ╎ ┏┅┅┓ ┋ ▍ ╲╱╲╱╳╳╳
║│╱ ╲│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╽ │┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▎
║└─╥─┘║ │╚═╤═╝│ │╘═╪═╛│ │╙─╀─╜│ ┃└─╂─┘┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▏
╚══╩══╝ └──┴──┘ ╰──┴──╯ ╰──┴──╯ ┗━━┻━━┛ ▗▄▖▛▀▜ └╌╌┘ ╎ ┗╍╍┛ ┋ ▁▂▃▄▅▆▇█
▝▀▘▙▄▟

View File

@ -0,0 +1,74 @@
//
// IOTests.swift
// SocketRocket
//
// Created by Mike Lewis on 7/31/15.
//
//
enum FailureError: ErrorType {
case Failure
}
import XCTest
@testable import SocketRocketIO
class IOTests: XCTestCase {
func testGetAddrInfoAsync() {
let promise: Promise<[addrinfo]> = getaddrinfoAsync("squareup.com", servname: "443")
.thenChecked { v in
let v = try v.checkedGet()
XCTAssertGreaterThan(v.count, 0)
return v
}
.thenChecked(Queue.mainQueue) { (v: ErrorOptional<[addrinfo]>) throws in
guard Queue.mainQueue.isCurrentQueue() else {
throw FailureError.Failure
}
return try v.checkedGet()
}
self.expectationWithPromise(promise)
}
func testGetAddrInfoAsyncFailure() {
let promise: Promise<[addrinfo]> = getaddrinfoAsync("", servname: "")
self.expectationWithFailingPromise(promise)
}
func testListen() {
return
do {
let acceptExpectation = expectationWithDescription("waiting")
let cancelGroup = dispatch_group_create()
dispatch_group_enter(cancelGroup)
let s = try Socket<sockaddr_in>(address: .Loopback, port: 9231)
let canceler = s.startAccepting(
Queue.mainQueue,
cancelHandler: {
dispatch_group_leave(cancelGroup)
},
acceptHandler: {
(fd) -> Void in
close(fd)
acceptExpectation.fulfill()
})
waitForExpectations()
let cancelExpection = expectationWithDescription("Canceled")
dispatch_group_notify(cancelGroup, dispatch_get_main_queue()) {
cancelExpection.fulfill()
}
canceler()
waitForExpectations()
} catch let e {
XCTFail("\(e)")
}
}
}

View File

@ -0,0 +1,24 @@
<?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>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>

View File

@ -0,0 +1,230 @@
//
// PromisesTests.swift
// SocketRocket
//
// Created by Mike Lewis on 8/3/15.
//
//
@testable import SocketRocketIO
import XCTest
class PromisesTests: XCTestCase {
func testAlreadyReady() {
let firstPromise = Promise.resolve(3)
let lastPromise = firstPromise
self.expectationWithPromise(lastPromise) { v in v == 3 }
}
func testAlreadyReady_chained() {
let lastPromise = Promise.resolve(3)
.thenSplit(success: { x in return .Promised(.resolve(x + 4)) })
.thenSplit(success: { v in return .of(v + 5) })
self.expectationWithPromise(lastPromise) { v in v == 12 }
}
func testNotReady_chained() {
let (r, p) = Promise<Int>.resolver()
let lastPromise = p
.thenSplit(success: { v in return .Promised(.resolve(v + 4)) })
.thenSplit(success: { v in return .of(v + 5) })
self.expectationWithPromise(lastPromise, wait: false) { v in v == 12 }
r.resolve(3)
self.waitForExpectations()
}
func testNotReady_chained2() {
let (r, p) = Promise<Int>.resolver()
let lastPromise = p
.thenSplit(success: { v in return .of(v + 4) })
.thenSplit(success: { v in return .of(v + 5) })
.then { val -> ErrorOptional<Int> in
switch val {
case .Error:
preconditionFailure("Should not get here")
case let .Some(v):
return .Some(v + 5)
}
}
self.expectationWithPromise(lastPromise, wait: false) { v in v == 17 }
r.resolve(3)
self.waitForExpectations()
}
func testDispatchesOnQueue_dispatchesOnQue() {
let (r, p) = Promise<Int>.resolver()
let e1 = self.expectationWithDescription("1")
let e2 = self.expectationWithDescription("2")
let q1 = Queue.defaultGlobalQueue
let q2 = Queue(label: "random queue")
let lastPromise = p
.thenChecked(q1) { v throws -> Int in
XCTAssertTrue(q1.isCurrentQueue())
e1.fulfill()
return try v.checkedGet() + 2
}
.thenChecked(q2) { v throws -> Int in
XCTAssertTrue(q2.isCurrentQueue())
e2.fulfill()
return try v.checkedGet() + 2
}
self.expectationWithPromise(lastPromise, wait: false) { v in v == 7 }
r.resolve(3)
self.waitForExpectations()
}
func testErrorHandling() {
self.expectationWithFailingPromise(Promise<Int>.reject(POSIXError.ENOEXEC)) { v in
switch v {
case POSIXError.ENOEXEC:
return true
default:
return false
}
}
let lastPromise = Promise.resolve(3)
.thenSplit { v in return .of(v + 4) }
.thenSplit { v in return .of(v + 5) }
.then { val -> ErrorOptional<Int> in
return .Error(POSIXError.ENODATA)
}
self.expectationWithFailingPromise(lastPromise)
}
func testOkChecked() {
let lastPromise = Promise.resolve(3)
.thenSplit { v in return .of(v + 4) }
.thenSplit { v in return .of(v + 5) }
.thenChecked { v throws in
return try v.checkedGet() + 3
}
self.expectationWithPromise(lastPromise) { v in
return v == 15
}
}
func testFailedChecked() {
let lastPromise = Promise.resolve(3)
.thenSplit { v in return .of(v + 4) }
.thenSplit { v in return .of(v + 5) }
.thenChecked { _ throws -> Int in
throw POSIXError.ENOENT
}
self.expectationWithFailingPromise(lastPromise) { v in
switch v {
case POSIXError.ENOENT:
return true
default:
return false
}
}
}
func testFailedCascade() {
let lastPromise = Promise.resolve(3)
.thenChecked { _ throws -> Int in
throw POSIXError.ECANCELED
}
.thenSplit { v in return .of(v + 4) }
.thenSplit { v in return .of(v + 5) }
.thenChecked { v throws -> Int in
try v.checkedGet()
throw POSIXError.ENOENT
}
self.expectationWithFailingPromise(lastPromise) { v in
switch v {
case POSIXError.ECANCELED:
return true
default:
return false
}
}
}
}
extension XCTestCase {
// Terminates a promise and returns an XCTestExpectation for it
func expectationWithPromise<T>(promise: Promise<T>, wait: Bool = true, file: String = __FILE__, line: UInt = __LINE__, predicate: (T) -> Bool = { _ in true}) -> XCTestExpectation {
let description = "Waiting for promise \(promise) to fulfill"
let expectation = self.expectationWithDescription(description)
promise.then { v in
switch v {
case .Error:
XCTFail("Promise failed for promise \(promise) for value \(v)", file:file, line:line)
case let .Some(newV):
if !predicate(newV) {
XCTFail("Predicate failed for promise \(promise) for value \(v)", file:file, line:line)
}
}
expectation.fulfill()
}
if wait {
self.waitForExpectations()
}
return expectation
}
// Terminates a promise and returns an XCTestExpectation for it
func expectationWithFailingPromise<T>(promise: Promise<T>, wait: Bool = true, file: String = __FILE__, line: UInt = __LINE__, predicate: (ErrorType) -> Bool = { _ in true}) -> XCTestExpectation {
let description = "Waiting for promise \(promise) to fulfill"
let expectation = self.expectationWithDescription(description)
promise.then { v in
switch v {
case let .Error(e):
if !predicate(e) {
XCTFail("Predicate failed for promise \(promise) for value \(v)", file:file, line:line)
}
case .Some:
XCTFail("Expected error for promise, but got value promise \(promise) for value \(v)", file:file, line:line)
}
expectation.fulfill()
}
if wait {
self.waitForExpectations()
}
return expectation
}
}

View File

@ -0,0 +1,258 @@
//
// QueueStreamable.swift
// SocketRocket
//
// Created by Mike Lewis on 8/5/15.
//
//
public protocol AsyncBaseStream {
/// The type we operate on
typealias Collection: CollectionType
}
public protocol AsyncReadable : AsyncBaseStream {
/// reads data until eof or size is reached. handler is invoked on the queue in order (and non-reentrant)
///
/// The return value of this indicates when the operation is done or if it failed
mutating func read(size: Collection.Index.Distance, queue: Queue, handler: (AnyRandomAccessCollection<Collection.Generator.Element>) throws -> ()) -> VoidPromiseType
}
public protocol AsyncWritable : AsyncBaseStream {
/// Writes data to the stream
///
/// THe return value of this indicates when the operation is done or if it failed
mutating func write<C: CollectionType where C.Generator.Element == Collection.Generator.Element>(data: C) -> VoidPromiseType
/// Closes the stream
mutating func close() -> VoidPromiseType
}
public extension AsyncReadable where Collection: RangeReplaceableCollectionType, Collection.Index.Distance == Int {
/// Buffers everything into one result
mutating func readAll(size: Collection.Index.Distance = Collection.Index.Distance.max , queue: Queue) -> Promise<Collection> {
var buffer = Collection()
let vp = read(size, queue: queue) { (v) -> () in
buffer.extend(v)
}
let (r, p) = Promise<Collection>.resolver()
vp.then { (voidP: ErrorOptional<Void>) -> () in
r.attemptResolve {
try voidP.checkedGet()
return buffer
}
}
return p
}
}
/// Wraps an io since it is a protocol
struct DispatchIO {
let io: dispatch_io_t
}
enum ValueOrEnd<V> {
/// :param consumed: the size of the input stream consumed
/// :param value: result value for the coded
case Value(V)
/// If we're out of data
case End
}
protocol Codec {
typealias InType: CollectionType
typealias OutType: CollectionType
// TODO(lewis): Maybe make this take chunks more for input
mutating func code(input: ValueOrEnd<AnyRandomAccessCollection<InType.Generator.Element>>) throws -> OutType
}
extension Codec where InType.Index : RandomAccessIndexType, InType: CollectionType {
mutating func code(input: ValueOrEnd<InType>) throws -> OutType {
switch input {
case let .Value(v):
let cc = AnyRandomAccessCollection<InType.Generator.Element>(v)
return try self.code(ValueOrEnd<AnyRandomAccessCollection<InType.Generator.Element>>.Value(cc))
case .End:
return try self.code(ValueOrEnd<AnyRandomAccessCollection<InType.Generator.Element>>.End)
}
}
}
//
struct EncodedReadable<C: Codec,
R: AsyncReadable
where R.Collection == C.InType,
C.InType.Index.Distance == C.OutType.Index.Distance,
C.OutType.Index: RandomAccessIndexType
>: AsyncReadable {
typealias Collection = C.OutType
private var input: R
private var codec: C
mutating func read(size: Collection.Index.Distance, queue: Queue, handler: (AnyRandomAccessCollection<Collection.Generator.Element>) throws -> ()) -> VoidPromiseType {
return input.read(size, queue: queue) { (e) -> () in
let coded = try self.codec.code(ValueOrEnd.Value(e))
try handler(AnyRandomAccessCollection(coded))
}.thenChecked { (vo: ErrorOptional<Void>) -> Void in
try handler(AnyRandomAccessCollection(self.codec.code(.End)))
try vo.checkedGet()
}
}
}
/// For testing
/// Probably not super efficient
public class Loopback<T: RangeReplaceableCollectionType
where
T.Index: RandomAccessIndexType,
T.Index.Distance == Int,
T.SubSequence.Generator.Element == T.Generator.Element,
T.SubSequence.Index : RandomAccessIndexType,
T.SubSequence: CollectionType
> : AsyncReadable, AsyncWritable {
public typealias Collection = T
public typealias ResultPromise = VoidPromiseType
public typealias Handler = (AnyRandomAccessCollection<T.Generator.Element>) throws -> ()
public typealias Distance = Collection.Index.Distance
let queue: Queue
var closed = false
var buffer = Collection()
var neededPromsises = [(size: Distance, resolver: Resolver<Void>, handler: Handler)]()
public init(queue: Queue) {
self.queue = queue
}
public func read(size: Collection.Index.Distance, queue: Queue, handler: (AnyRandomAccessCollection<Collection.Generator.Element>) throws -> ()) -> VoidPromiseType {
let (r, p) = VoidPromiseType.resolver()
queue.dispatchAsync {
self.neededPromsises.append((size: size, resolver: r, handler: handler))
self.produce()
}
return p
}
public func write<C: CollectionType where C.Generator.Element == Collection.Generator.Element>(data: C) -> VoidPromiseType {
let (r, p) = VoidPromiseType.resolver()
let data = Collection() + data
queue.dispatchAsync {
precondition(!self.closed)
self.buffer.extend(data)
r.resolve()
self.queue.dispatchAsync {
self.produce()
}
}
return p
}
func produce() {
do {
while neededPromsises.count > 0 && buffer.count > 0 {
let (size, resolver, handler) = neededPromsises[0]
let numBytes = min(size, buffer.count)
let newSize = size - numBytes
let usedRange = buffer.startIndex..<buffer.startIndex.advancedBy(numBytes)
let slice = buffer[usedRange]
let newC = AnyRandomAccessCollection<T.SubSequence.Generator.Element>(slice)
precondition(slice.count > 0)
precondition(newC.count > 0)
try handler(newC)
buffer.replaceRange(usedRange, with: Collection())
if newSize == 0 {
resolver.resolve()
neededPromsises.removeAtIndex(0)
} else {
neededPromsises[0] = (newSize, resolver, handler)
}
}
if closed && buffer.isEmpty {
for p in self.neededPromsises {
p.resolver.resolve()
}
self.neededPromsises.removeAll()
}
} catch let e {
for p in self.neededPromsises {
p.resolver.reject(e)
}
self.neededPromsises.removeAll()
}
}
public func close() -> ResultPromise {
let (r, p) = VoidPromiseType.resolver()
queue.dispatchAsync {
self.closed = true
self.produce()
r.resolve()
}
return p
}
}
extension Queue {
static let defaultCleanupQueue = Queue.defaultGlobalQueue
}
/// Chains two generators together
struct ChainedGenerator<L: GeneratorType, R: GeneratorType, T where L.Element == R.Element, T == L.Element>: GeneratorType, SequenceType {
typealias Element = T
typealias Generator = ChainedGenerator<L, R, T>
var l: L
var r: R
var onfirst = true
init(lhs: L, rhs: R) {
l = lhs
r = rhs
}
mutating func next() -> Element? {
if onfirst {
if let v = l.next() {
return v
} else {
onfirst = false
}
}
return r.next()
}
}
func + <L: GeneratorType, R: GeneratorType, T where L.Element == R.Element, T == L.Element >(lhs: L, rhs: R) -> ChainedGenerator<L, R, T> {
return ChainedGenerator(lhs: lhs, rhs: rhs)
}

View File

@ -0,0 +1,99 @@
//
// QueueStreamableTests.swift
// SocketRocket
//
// Created by Mike Lewis on 8/6/15.
//
//
import XCTest
@testable import SocketRocketIO
class QueueStreamableTests: XCTestCase {
static let filePath = NSBundle(forClass: QueueStreamableTests.self).pathForResource("FileToReadFrom", ofType: "txt", inDirectory: "Fixtures")!
func testManualAccumulating() {
let io = dispatch_io_create_with_path(DISPATCH_IO_STREAM, QueueStreamableTests.filePath, O_RDONLY, 0, Queue.mainQueue.queue) { _ in }
let streamer = DispatchIO(io: io)
var accumulated = [UInt8]()
let readQueue = Queue(label: "Read queue")
let p = streamer.read(Int.max, queue: readQueue) { data in
accumulated += data
}
expectationWithPromise(p)
dispatch_io_close(io, 0)
let readData = String(bytes:accumulated, encoding: NSUTF8StringEncoding)
XCTAssertEqual(readData!, "hello\nthis\nis a file\n\nI like to read from it")
}
func testErrorHandling() {
let io = dispatch_io_create_with_path(DISPATCH_IO_STREAM, QueueStreamableTests.filePath, O_RDONLY, 0, Queue.mainQueue.queue) { _ in }
let streamer = DispatchIO(io: io)
let readQueue = Queue(label: "Read queue")
dispatch_suspend(readQueue.queue)
let f = streamer.read(Int.max, queue: readQueue) { v in
}
dispatch_io_close(streamer.io, DISPATCH_IO_STOP)
dispatch_resume(readQueue.queue)
expectationWithFailingPromise(f)
}
func testLoopback() {
let q = Queue(label: "loopbackQueue")
var l = Loopback<[UInt8]>(queue: q)
let p = l.readAll(queue: q).thenChecked { v in
let v = try v.checkedGet()
XCTAssertEqual(v, [UInt8]("OMG PONIESI LIKE TO EAT PONIES".utf8))
}
l.write([UInt8]("OMG PONIES".utf8))
l.write([UInt8]("I LIKE TO EAT PONIES".utf8))
expectationWithPromise(l.close(), wait: false)
expectationWithPromise(p)
}
}
extension POSIXError: CustomDebugStringConvertible {
public var debugDescription: String {
get {
var buffer = [CChar](count: 1024, repeatedValue: 0)
guard strerror_r(rawValue, &buffer, buffer.count) == 0 else {
return "Unknown!!"
}
return "Posix Error \(rawValue) " + (String.fromCString(&buffer) ?? "Issue converting to cstring")
}
}
}
func XCTAssertEqualT<T : Equatable>(@autoclosure expression1: () throws -> T, @autoclosure _ expression2: () -> T, _ message: String = "", file: String = __FILE__, line: UInt = __LINE__)
{
do {
let v = try expression1()
XCTAssertEqual(v, expression2(), line: line, file:file)
} catch let e {
XCTFail("\(e)", line: line, file:file)
}
}

View File

@ -0,0 +1,61 @@
//
// QueueTests.swift
// SocketRocket
//
// Created by Mike Lewis on 7/30/15.
//
//
import XCTest
import SocketRocketIO
class QueueTests: XCTestCase {
func testMainQueue() {
let queue = Queue.mainQueue
let expectation = expectationWithDescription("Should dispatch")
queue.dispatchAsync {
expectation.fulfill()
}
waitForExpectations()
}
func testMainQueueRecognizesSelf() {
let expectation = expectationWithDescription("Should dispatch")
let queue = Queue.mainQueue
queue.dispatchAsync {
XCTAssertTrue(Queue.mainQueue.isCurrentQueue())
expectation.fulfill()
}
waitForExpectations()
}
func testCheckIsCurrentQueue() {
let expectation = expectationWithDescription("Should dispatch")
let queue = Queue(label: "queueLabel")
queue.dispatchAsync {
XCTAssertTrue(queue.isCurrentQueue())
queue.checkIsCurrentQueue()
expectation.fulfill()
}
waitForExpectations()
XCTAssertFalse(queue.isCurrentQueue())
}
}
let defaultTimeout: NSTimeInterval = 10
extension XCTestCase {
func waitForExpectations() -> Void {
waitForExpectationsWithTimeout(defaultTimeout, handler: nil)
}
}

View File

@ -0,0 +1,35 @@
//
// SocketRocketIOTests.swift
// SocketRocketIOTests
//
// Created by Mike Lewis on 7/30/15.
//
//
import XCTest
@testable import SocketRocketIO
class SocketRocketIOTests: XCTestCase {
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}
func testExample() {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
func testPerformanceExample() {
// This is an example of a performance test case.
self.measureBlock {
// Put the code you want to measure the time of here.
}
}
}

View File

@ -0,0 +1,183 @@
//
// UnicodeTests.swift
// SocketRocket
//
// Created by Mike Lewis on 8/6/15.
//
//
import XCTest
@testable import SocketRocketIO
struct SourceInfo {
let line: UInt
let file: String
init(line: UInt = __LINE__, file: String = __FILE__) {
self.line = line
self.file = file
}
}
typealias SI = SourceInfo
class UnicodeTests: XCTestCase {
func testCodeUnits() {
let s = "💩1💩"
var data = [UInt8]()
for s in s.unicodeScalars {
UTF8.encode(s) { (cu) -> () in
data.append(cu)
}
}
XCTAssertEqualT(try UTF8.numValidCodeUnits(data.generate()), 9)
XCTAssertEqualT(try UTF8.numValidCodeUnits(data[0..<8].generate()), 5)
XCTAssertEqualT(try UTF8.numValidCodeUnits(data[0..<5].generate()), 5)
XCTAssertEqualT(try UTF8.numValidCodeUnits(data[0..<4].generate()), 4)
XCTAssertEqualT(try UTF8.numValidCodeUnits(data[0..<3].generate()), 0)
}
func testDecoding() {
var uc = UTF8()
let s = "💩1💩"
var data = [UInt8]()
for s in s.unicodeScalars {
UTF8.encode(s) { (cu) -> () in
data.append(cu)
}
}
XCTAssertEqual(data.count, 9)
var c = RawUTF8Codec<ArraySlice<UInt8>, ArraySlice<UInt8>.Generator>()
var buff = String()
func accumulate(slice: ArraySlice<UInt8>, line: UInt = __LINE__, file: String = __FILE__) {
do {
buff.unicodeScalars.extend(try c.code(ValueOrEnd.Value(slice)))
} catch let e {
XCTFail("\(e)", line:line, file:file)
}
}
accumulate(data[0..<2])
accumulate(data[2..<3])
accumulate(data[3..<8])
accumulate(data[8..<9])
do {
let r = try c.code(.End)
XCTAssertEqual("", String(r))
} catch let e {
XCTFail("\(e)")
}
XCTAssertEqual(buff, s)
}
func testDecoding_errorHandling() {
var uc = UTF8()
let s = "💩1💩"
var data = [UInt8]()
for s in s.unicodeScalars {
UTF8.encode(s) { (cu) -> () in
data.append(cu)
}
}
XCTAssertEqual(data.count, 9)
var c = RawUTF8Codec<ArraySlice<UInt8>, ArraySlice<UInt8>.Generator>()
var buff = String()
func accumulate(slice: ArraySlice<UInt8>, line: UInt = __LINE__, file: String = __FILE__) {
do {
let v = try c.code(ValueOrEnd.Value(slice))
buff.unicodeScalars.extend(v)
} catch let e {
XCTFail("\(e)", line:line, file:file)
}
}
accumulate(data[0..<2])
accumulate(data[2..<3])
accumulate(data[3..<8])
do {
try c.code(.End)
XCTFail("Should except")
} catch {
}
}
func testDecoding_Smoke() {
let filePath = NSBundle(forClass: QueueStreamableTests.self).pathForResource("UTF8Sample", ofType: "txt", inDirectory: "Fixtures")!
let s = NSData(contentsOfFile: filePath)!
let nominalString = NSString(data: s, encoding: NSUTF8StringEncoding) as! String
doTestAccumulateSplit(nominalString, splitPoints: [Int](0..<(s.length - 1)))
doTestAccumulateSplit(nominalString, splitPoints: [])
doTestAccumulateSplit(nominalString, splitPoints: [Int](0..<((s.length - 1) / 2)).map({e in return e / 2}))
}
func doTestAccumulateSplit(data: [UInt8], var splitPoints: [Int], si: SI = SI()) -> String {
var c = RawUTF8Codec<ArraySlice<UInt8>, ArraySlice<UInt8>.Generator>()
var buff = String()
func accumulate(slice: ArraySlice<UInt8>, si: SI) {
do {
let v = try c.code(ValueOrEnd.Value(slice))
buff.unicodeScalars.extend(v)
} catch let e {
XCTFail("\(e)")
XCTFail("\(e) (from here)", line:si.line, file:si.file)
}
}
splitPoints.sortInPlace()
var lastIdx = data.startIndex
for sp in splitPoints {
let newIdx = data.startIndex.advancedBy(sp)
accumulate(data[lastIdx..<newIdx], si: si)
lastIdx = newIdx
}
accumulate(data[lastIdx..<data.endIndex], si: si)
do {
try c.code(.End)
} catch let e {
XCTFail("Should not except \(e)")
}
return buff
}
func doTestAccumulateSplit(string: String, splitPoints: [Int], si: SI = SI()) {
var data = [UInt8]()
for s in string.unicodeScalars {
UTF8.encode(s) { (cu) -> () in
data.append(cu)
}
}
let r = doTestAccumulateSplit(data, splitPoints: splitPoints, si: si)
XCTAssertEqual(string, r, line:si.line, file:si.file)
}
}

View File

@ -9,7 +9,7 @@
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>com.squareup.${PRODUCT_NAME:rfc1034identifier}</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>

26
SystemShims/Info.plist Normal file
View File

@ -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>

23
SystemShims/SystemShims.h Normal file
View File

@ -0,0 +1,23 @@
//
// SystemShims.h
// SystemShims
//
// Created by Mike Lewis on 7/31/15.
//
//
#import <UIKit/UIKit.h>
//! Project version number for SystemShims.
FOUNDATION_EXPORT double SystemShimsVersionNumber;
//! Project version string for SystemShims.
FOUNDATION_EXPORT const unsigned char SystemShimsVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <SystemShims/PublicHeader.h>
extern int shim_fcntl(int fildes, int cmd, int flags);
extern int shim_bind(int fildes, const void *addr, size_t size);
extern int shim_accept(int fildes, void *addr, socklen_t *size);

24
SystemShims/SystemShims.m Normal file
View File

@ -0,0 +1,24 @@
//
// SystemShims.c
// SocketRocket
//
// Created by Mike Lewis on 7/31/15.
//
//
#import "SystemShims.h"
#import <sys/fcntl.h>
#import <sys/socket.h>
extern int shim_fcntl(int fildes, int cmd, int flags) {
return fcntl(fildes, cmd, flags);
}
extern int shim_bind(int fildes, const void *addr, size_t size) {
return bind(fildes, addr, (socklen_t)size);
}
extern int shim_accept(int fildes, void *addr, socklen_t *size) {
return accept(fildes, addr, size);
}

View File

@ -1,61 +0,0 @@
//
// TCAppDelegate.m
// TestChat
//
// Created by Mike Lewis on 1/28/12.
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//
#import "TCAppDelegate.h"
@implementation TCAppDelegate
@synthesize window = _window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
/*
Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
*/
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
/*
Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
*/
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
/*
Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
*/
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
/*
Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
*/
}
- (void)applicationWillTerminate:(UIApplication *)application
{
/*
Called when the application is about to terminate.
Save data if appropriate.
See also applicationDidEnterBackground:.
*/
}
@end

130
TestChat/TCAppDelegate.mm Normal file
View File

@ -0,0 +1,130 @@
//
// TCAppDelegate.m
// TestChat
//
// Created by Mike Lewis on 1/28/12.
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//
#import "TCAppDelegate.h"
#import <Security/SecureTransport.h>
#import "SecureIO.h"
#import <string>
using namespace squareup::dispatch;
@implementation TCAppDelegate {
SecureIO *_io;
}
@synthesize window = _window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
/*
Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
*/
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
/*
Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
*/
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
/*
Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
*/
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
SSLContextRef ctx = SSLCreateContext(CFAllocatorGetDefault(), kSSLClientSide, kSSLStreamType);
auto finishBlock = [self](int error) {
NSLog(@"Done");
};
dispatch_queue_t workQueue = dispatch_queue_create("squareup.dispatch work queue", DISPATCH_QUEUE_SERIAL);
DialTLS("localhost", "10248", ctx, dispatch_get_main_queue(), workQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), [self, _cmd](squareup::dispatch::SecureIO *io, int error, const char *error_message) {
NSAssert(error == 0, @"Should not have errored, but got %s", error_message);
NSAssert(io != nullptr, @"io should be valid");
if (!io) {
return;
}
_io = io;
__block bool seenInner = false;
__block bool seenOuter = false;
// _io->Write(Data("HELLO THERE!\n", dispatch_get_main_queue()), ^(bool done, dispatch_data_t data, int error) {
// STAssertEquals(error, 0, @"Error should == 0");
// STAssertFalse(seenOuter, @"Should only see the outer once");
// if (done) {
// seenOuter = true;
// }
// if (done && !error) {
//
// }
// });
//
// _io->Write(Data("HELLO THERE2!\n", dispatch_get_main_queue()), ^(bool done, dispatch_data_t data, int error) {
// STAssertFalse(seenInner, @"Shouldn't have seen inner yet");
// if (done) {
// seenInner = done;
// }
// STAssertEquals(error, 0, @"Error should == 0");
// STAssertFalse(finished, @"Shouldn't have finished");
// });
for (int i = 0; i < 4096; i++) {
_io->Read(1024 * 1024* 13, dispatch_get_main_queue(), [self, _cmd, i](bool readDone, dispatch_data_t data, int error) {
if (!error) {
_io->Write(data, dispatch_get_main_queue(), [self, readDone, i](bool done, dispatch_data_t data, int error) {
});
} else {
NSAssert(error == ECANCELED, @"Server should terminate");
if (readDone && !error) {
_io->Close(0);
}
}
});
}
}, finishBlock);
/*
Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
*/
}
- (void)applicationWillTerminate:(UIApplication *)application
{
/*
Called when the application is about to terminate.
Save data if appropriate.
See also applicationDidEnterBackground:.
*/
}
@end

View File

@ -11,7 +11,7 @@
<key>CFBundleIconFiles</key>
<array/>
<key>CFBundleIdentifier</key>
<string>com.squareup.${PRODUCT_NAME:rfc1034identifier}</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>

View File

@ -0,0 +1,96 @@
package main
import (
"bytes"
"crypto/rand"
"crypto/tls"
"io"
"io/ioutil"
"log"
"net"
)
func main() {
keyPair, err := tls.LoadX509KeyPair("cert.pem", "key.pem")
if err != nil {
panic(err)
}
cfg := &tls.Config{
Certificates: []tls.Certificate{keyPair},
}
listener, err := tls.Listen("tcp", ":10248", cfg)
if err != nil {
panic(err)
}
for conn, err := listener.Accept(); err == nil; conn, err = listener.Accept() {
go func(conn net.Conn) {
defer func() {
if err := recover(); err != nil {
log.Println("Something failed:", err)
}
}()
ch := make(chan bool, 1)
maxPending := make(chan bool, 2)
chunkSize := int64(1024 * 1024)
buff2 := bytes.NewBuffer(make([]byte, 0, chunkSize))
randBytes := make([]byte, chunkSize)
_, err := rand.Read(randBytes)
if err != nil {
panic(err)
}
randReader := bytes.NewReader(randBytes)
ch <- true
go func() {
defer func() {
if err := recover(); err != nil {
log.Println("Something failed:", err)
}
}()
defer func() {
<-ch
}()
for i := 0; ; i++ {
defer func() {
if err := recover(); err != nil {
log.Println("Something failed:", err)
}
}()
_, err := io.CopyN(ioutil.Discard, conn, chunkSize)
if err != nil {
panic(err)
}
<-maxPending
log.Println("Chunk read back (", i, ")")
}
buff2.Reset()
}()
for {
maxPending <- true
randReader.Seek(0, 0)
_, err := io.CopyN(conn, randReader, chunkSize)
if err != nil {
panic(err)
}
}
ch <- true
conn.Close()
}(conn)
}
if err != nil {
panic(err)
}
}