Skip to content
Browse files

Finishing implementation of the Hixie, tests and main classes.

  • Loading branch information...
1 parent 03b4507 commit 8d1d9786f1f7b7d18a533e8ad83e100b27713036 @pk committed
View
16 PKWebSocket.xcodeproj/project.pbxproj
@@ -17,13 +17,14 @@
E9008DC4153DD3F10038591B /* PKWebSocketCrypto.m in Sources */ = {isa = PBXBuildFile; fileRef = E9008DC2153DD3F10038591B /* PKWebSocketCrypto.m */; };
E9008DC8153DD5880038591B /* PKWebSocketHandler-Hixie75Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = E9008DC6153DD5880038591B /* PKWebSocketHandler-Hixie75Tests.m */; };
E9008DC9153DD5880038591B /* PKWebSocketHandler-Hixie76Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = E9008DC7153DD5880038591B /* PKWebSocketHandler-Hixie76Tests.m */; };
- E9008DF0153DFBFF0038591B /* PKWebSocketHandlerProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = E9008DEF153DFBFF0038591B /* PKWebSocketHandlerProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
E9008DF3153DFE2B0038591B /* PKWebSocketHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = E9008DF1153DFE2B0038591B /* PKWebSocketHandler.h */; settings = {ATTRIBUTES = (Public, ); }; };
E9008DF4153DFE2B0038591B /* PKWebSocketHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = E9008DF2153DFE2B0038591B /* PKWebSocketHandler.m */; };
E9008DFE153E06870038591B /* NSData+PKWebSocketBase64.h in Headers */ = {isa = PBXBuildFile; fileRef = E9008DFC153E06870038591B /* NSData+PKWebSocketBase64.h */; settings = {ATTRIBUTES = (Public, ); }; };
E9008DFF153E06870038591B /* NSData+PKWebSocketBase64.m in Sources */ = {isa = PBXBuildFile; fileRef = E9008DFD153E06870038591B /* NSData+PKWebSocketBase64.m */; };
E9008E03153E07E80038591B /* PKWebSocketHandler-RFC6455Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = E9008E02153E07E80038591B /* PKWebSocketHandler-RFC6455Tests.m */; };
E91A30EA153C8FE80015C038 /* PKWebSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = E994C273153C3DF00078AA11 /* PKWebSocket.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E93F46CC15437E3000777C1F /* PKWebSocketMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = E93F46CA15437E3000777C1F /* PKWebSocketMessage.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E93F46CD15437E3000777C1F /* PKWebSocketMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = E93F46CB15437E3000777C1F /* PKWebSocketMessage.m */; };
E9773E7F153CCD7100D8C582 /* PKWebSocketHandler-RFC6455.h in Headers */ = {isa = PBXBuildFile; fileRef = E9773E7D153CCD7100D8C582 /* PKWebSocketHandler-RFC6455.h */; settings = {ATTRIBUTES = (Public, ); }; };
E9773E80153CCD7100D8C582 /* PKWebSocketHandler-RFC6455.m in Sources */ = {isa = PBXBuildFile; fileRef = E9773E7E153CCD7100D8C582 /* PKWebSocketHandler-RFC6455.m */; };
E9773E83153CCDA300D8C582 /* PKHTTPRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = E9773E81153CCDA300D8C582 /* PKHTTPRequest.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -54,7 +55,6 @@
E9E066BD1540771E008AC7EF /* PKWebSocketConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = E9E066BB1540771E008AC7EF /* PKWebSocketConstants.m */; };
E9F346C1153C40300052DAAE /* AsyncSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = E9F346BF153C40300052DAAE /* AsyncSocket.h */; settings = {ATTRIBUTES = (Public, ); }; };
E9F346C2153C40300052DAAE /* AsyncSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = E9F346C0153C40300052DAAE /* AsyncSocket.m */; };
- E9F346C5153C425E0052DAAE /* PKWebSocketDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = E9F346C4153C425E0052DAAE /* PKWebSocketDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -77,12 +77,13 @@
E9008DC2153DD3F10038591B /* PKWebSocketCrypto.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PKWebSocketCrypto.m; path = Categories/PKWebSocketCrypto.m; sourceTree = "<group>"; };
E9008DC6153DD5880038591B /* PKWebSocketHandler-Hixie75Tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "PKWebSocketHandler-Hixie75Tests.m"; sourceTree = "<group>"; };
E9008DC7153DD5880038591B /* PKWebSocketHandler-Hixie76Tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "PKWebSocketHandler-Hixie76Tests.m"; sourceTree = "<group>"; };
- E9008DEF153DFBFF0038591B /* PKWebSocketHandlerProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PKWebSocketHandlerProtocol.h; sourceTree = "<group>"; };
E9008DF1153DFE2B0038591B /* PKWebSocketHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PKWebSocketHandler.h; sourceTree = "<group>"; };
E9008DF2153DFE2B0038591B /* PKWebSocketHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PKWebSocketHandler.m; sourceTree = "<group>"; };
E9008DFC153E06870038591B /* NSData+PKWebSocketBase64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSData+PKWebSocketBase64.h"; path = "Categories/NSData+PKWebSocketBase64.h"; sourceTree = "<group>"; };
E9008DFD153E06870038591B /* NSData+PKWebSocketBase64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSData+PKWebSocketBase64.m"; path = "Categories/NSData+PKWebSocketBase64.m"; sourceTree = "<group>"; };
E9008E02153E07E80038591B /* PKWebSocketHandler-RFC6455Tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "PKWebSocketHandler-RFC6455Tests.m"; sourceTree = "<group>"; };
+ E93F46CA15437E3000777C1F /* PKWebSocketMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PKWebSocketMessage.h; sourceTree = "<group>"; };
+ E93F46CB15437E3000777C1F /* PKWebSocketMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PKWebSocketMessage.m; sourceTree = "<group>"; };
E9773E7D153CCD7100D8C582 /* PKWebSocketHandler-RFC6455.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "PKWebSocketHandler-RFC6455.h"; sourceTree = "<group>"; };
E9773E7E153CCD7100D8C582 /* PKWebSocketHandler-RFC6455.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "PKWebSocketHandler-RFC6455.m"; sourceTree = "<group>"; };
E9773E81153CCDA300D8C582 /* PKHTTPRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PKHTTPRequest.h; sourceTree = "<group>"; };
@@ -116,7 +117,6 @@
E9E066BB1540771E008AC7EF /* PKWebSocketConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PKWebSocketConstants.m; sourceTree = "<group>"; };
E9F346BF153C40300052DAAE /* AsyncSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AsyncSocket.h; path = Submodules/CocoaAsyncSocket/RunLoop/AsyncSocket.h; sourceTree = "<group>"; };
E9F346C0153C40300052DAAE /* AsyncSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AsyncSocket.m; path = Submodules/CocoaAsyncSocket/RunLoop/AsyncSocket.m; sourceTree = "<group>"; };
- E9F346C4153C425E0052DAAE /* PKWebSocketDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PKWebSocketDelegate.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -220,16 +220,16 @@
E9773E7C153CCD7100D8C582 /* Handlers */,
E994C273153C3DF00078AA11 /* PKWebSocket.h */,
E994C274153C3DF00078AA11 /* PKWebSocket.m */,
- E9F346C4153C425E0052DAAE /* PKWebSocketDelegate.h */,
E9773E81153CCDA300D8C582 /* PKHTTPRequest.h */,
E9773E82153CCDA300D8C582 /* PKHTTPRequest.m */,
E9773E85153CCDB000D8C582 /* PKHTTPResponse.h */,
E9773E86153CCDB000D8C582 /* PKHTTPResponse.m */,
- E9008DEF153DFBFF0038591B /* PKWebSocketHandlerProtocol.h */,
E9E06686153F6AEF008AC7EF /* PKWebSocketURL.h */,
E9E06687153F6AEF008AC7EF /* PKWebSocketURL.m */,
E9E066BA1540771E008AC7EF /* PKWebSocketConstants.h */,
E9E066BB1540771E008AC7EF /* PKWebSocketConstants.m */,
+ E93F46CA15437E3000777C1F /* PKWebSocketMessage.h */,
+ E93F46CB15437E3000777C1F /* PKWebSocketMessage.m */,
E994C271153C3DF00078AA11 /* Supporting Files */,
);
path = PKWebSocket;
@@ -311,12 +311,10 @@
buildActionMask = 2147483647;
files = (
E9F346C1153C40300052DAAE /* AsyncSocket.h in Headers */,
- E9F346C5153C425E0052DAAE /* PKWebSocketDelegate.h in Headers */,
E91A30EA153C8FE80015C038 /* PKWebSocket.h in Headers */,
E9773E7F153CCD7100D8C582 /* PKWebSocketHandler-RFC6455.h in Headers */,
E9773E9B153CFAD400D8C582 /* PKWebSocketHandler-Hixie75.h in Headers */,
E9008DBC153DAFEA0038591B /* PKWebSocketHandler-Hixie76.h in Headers */,
- E9008DF0153DFBFF0038591B /* PKWebSocketHandlerProtocol.h in Headers */,
E9008DF3153DFE2B0038591B /* PKWebSocketHandler.h in Headers */,
E9E06688153F6AEF008AC7EF /* PKWebSocketURL.h in Headers */,
E9773E83153CCDA300D8C582 /* PKHTTPRequest.h in Headers */,
@@ -326,6 +324,7 @@
E9CCF385154172390019878B /* PKWebSocketFrame-Hixie76.h in Headers */,
E9CCF3A0154199150019878B /* PKWebSocketFrame.h in Headers */,
E9008DFE153E06870038591B /* NSData+PKWebSocketBase64.h in Headers */,
+ E93F46CC15437E3000777C1F /* PKWebSocketMessage.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -441,6 +440,7 @@
E9E066BD1540771E008AC7EF /* PKWebSocketConstants.m in Sources */,
E9CCF386154172390019878B /* PKWebSocketFrame-Hixie76.m in Sources */,
E9CCF3A1154199150019878B /* PKWebSocketFrame.m in Sources */,
+ E93F46CD15437E3000777C1F /* PKWebSocketMessage.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
83 PKWebSocket/Categories/NSData+PKWebSocketCrypto.m
@@ -1,83 +0,0 @@
-//
-// NSData+PKWebSocketCrypto.m
-// PKWebSocket
-//
-// Created by Pavel Kunc on 17/04/2012.
-// Copyright (c) 2012 Pavel Kunc. All rights reserved.
-//
-
-#import "NSData+PKWebSocketCrypto.h"
-
-@implementation NSData (PKWebSocketCrypto)
-
-- (NSData *)pk_MD5 {
- NSMutableData *digest = [NSMutableData dataWithLength:CC_MD5_DIGEST_LENGTH];
- CC_MD5([self bytes], (unsigned)[self length], [digest mutableBytes]);
- return (NSData *)digest;
-}
-
-- (NSData *)pk_SHA1 {
- NSMutableData *digest = [NSMutableData dataWithLength:CC_SHA1_DIGEST_LENGTH];
- CC_SHA1([self bytes], (unsigned)[self length], [digest mutableBytes]);
- return (NSData *)digest;
-}
-
-+ (NSData *)pk_randomBytesOfLength:(NSUInteger)aLength {
- NSMutableData *random = [NSMutableData dataWithLength:aLength];
- arc4random_buf([random mutableBytes], aLength);
- return (NSData *)random;
-}
-
-@end
-
-SecKey pkws_hixie76Key() {
- struct SecKey seckey;
- uint32_t spaces, max, num, prod;
- NSInteger keylen;
- unichar letter;
- NSString *space = @" ";
-
- do {
- spaces = (arc4random() % 12) + 1;
- // As per 5.2.5, abort the connection if spaces are zero.
- assert(spaces > 0 && spaces <= 12);
-
- max = (arc4random() % 4294967295U) / spaces;
- assert(max >= 0 && max <= 4294967295U);
-
- num = arc4random() % max;
- assert(num >= 0 && num <= max);
-
- prod = spaces * num;
- } while (pkws_numberOfDigits(prod) % spaces != 0);
-
- NSMutableString *key = [NSMutableString stringWithFormat:@"%ld", prod];
- keylen = [key length];
-
- // As per 5.2.6, abort if numbers is not an integral multiple of spaces
- assert(keylen % spaces != 0);
-
- for (NSUInteger i = 0; i < 12; i++) {
- if ((arc4random() % 2) == 0)
- letter = (arc4random() % (47 - 33 + 1)) + 33;
- else
- letter = (arc4random() % (126 - 58 + 1)) + 58;
-
- NSUInteger index = (arc4random() % (keylen-1));
- NSString *letterString = [[NSString alloc] initWithCharacters:&letter length:1];
- [key insertString:letterString atIndex:index];
- }
-
- keylen = [key length];
-
- for (NSUInteger i = 0; i < spaces; i++) {
- NSUInteger index = ((arc4random() % (keylen-2))+1);
- [key insertString:space atIndex:index];
- }
-
- seckey.num = num;
- seckey.key = key;
-
- return seckey;
-}
-
View
1 PKWebSocket/Categories/PKWebSocketCrypto.m
@@ -101,4 +101,3 @@ SecKey pkws_hixie76Key() {
return seckey;
}
-
View
53 PKWebSocket/Frames/PKWebSocketFrame-Hixie76.m
@@ -51,6 +51,7 @@ - (void)processData:(NSData *)aData {
// High order bit set
char b;
do {
+ // If we don't have more data get out before exception
if (pointer + 1 > [aData length]) break;
[aData getBytes:&b range:NSMakeRange(pointer,1)];
pointer++;
@@ -63,10 +64,13 @@ - (void)processData:(NSData *)aData {
// Closing handshake frame
[self.delegate frame:self initiateClosingHandshakeWithData:self.closingPayload];
finished = YES;
- } else if (length > [aData length]) {
+ } else if (length > [aData length] - pointer) {
+ // If there is not enough data in the frame it's incomplete frame
+ NSString *reason = [NSString stringWithFormat:@"We're supposed to read %d bytes but we only have %d bytes.",length,[aData length]];
+ NSDictionary *ui = [NSDictionary dictionaryWithObjectsAndKeys:reason, NSLocalizedDescriptionKey, nil];
NSError *error = [NSError errorWithDomain:PKWebSocketErrorDomain
code:PKWebSocketFrameIncompleteFrame
- userInfo:nil];
+ userInfo:ui];
[self.delegate frame:self didProcessString:nil error:error];
finished = YES;
} else {
@@ -75,19 +79,50 @@ - (void)processData:(NSData *)aData {
}
} else {
if (frameType != 0x00) {
+ NSString *reason = @"Text frame must start with 0x00.";
+ NSDictionary *ui = [NSDictionary dictionaryWithObjectsAndKeys:reason, NSLocalizedDescriptionKey, nil];
NSError *error = [NSError errorWithDomain:PKWebSocketErrorDomain
code:PKWebSocketFrameInvalidFrame
- userInfo:nil];
+ userInfo:ui];
[self.delegate frame:self didProcessString:nil error:error];
+ finished = YES;
} else {
// Text frame
- NSRange range = NSMakeRange(pointer, [aData length] - pointer - 1);
- NSData *data = [aData subdataWithRange:range];
- NSString *text = [[NSString alloc] initWithData:data
- encoding:NSUTF8StringEncoding];
- [self.delegate frame:self didProcessString:text error:nil];
+
+ // We read data till we reach 0xFF and copy that to the buffer
+ // keeping pointer in sync.
+ char byte;
+ NSMutableData *buffer = [NSMutableData dataWithCapacity:[aData length] - pointer];
+ NSRange range = NSMakeRange(pointer, 1);
+ [aData getBytes:&byte range:range];
+ pointer++;
+
+ while ((byte & 0xFF) != 0xFF && pointer < [aData length]) {
+ [buffer appendBytes:&byte length:1];
+
+ NSRange range = NSMakeRange(pointer, 1);
+ [aData getBytes:&byte range:range];
+ pointer++;
+ }
+
+ // Convert data to UTF-8 String
+ NSError *error = nil;
+ NSString *text = [[NSString alloc] initWithData:buffer encoding:NSUTF8StringEncoding];
+ if (text == nil) {
+ NSString *reason = @"Unable to create UTF-8 string from data, missing 0xFF probably.";
+ NSDictionary *ui = [NSDictionary dictionaryWithObjectsAndKeys:reason, NSLocalizedDescriptionKey, nil];
+ error = [NSError errorWithDomain:PKWebSocketErrorDomain
+ code:PKWebSocketFrameInvalidFrame
+ userInfo:ui];
+ finished = YES;
+ }
+ [self.delegate frame:self didProcessString:text error:error];
+
+ // We reached end of data so we're finished
+ if (pointer == [aData length]) {
+ finished = YES;
+ }
}
- finished = YES;
}
}
}
View
2 PKWebSocket/Frames/PKWebSocketFrame.h
@@ -29,5 +29,7 @@
- (void)processData:(NSData *)data;
- (NSData *)textFramePayloadWithString:(NSString *)string;
+- (NSData *)binaryFramePayloadWithData:(NSData *)aData;
@end
+
View
5 PKWebSocket/Frames/PKWebSocketFrame.m
@@ -22,4 +22,9 @@ - (NSData *)textFramePayloadWithString:(NSString *)string {
return nil;
}
+- (NSData *)binaryFramePayloadWithData:(NSData *)aData {
+ NSAssert(nil, @"Must be implemented in the sub-class!");
+ return nil;
+}
+
@end
View
26 PKWebSocket/Handlers/PKWebSocketHandler.h
@@ -14,30 +14,37 @@
@class PKHTTPResponse;
@class PKWebSocketURL;
@class PKWebSocketFrame;
-@class PKWebSocket;
+@class PKWebSocketMessage;
+@class PKWebSocketHandler;
+
+@protocol PKWebSocketHandlerDelegate <NSObject>
+- (void)handler:(PKWebSocketHandler *)handler didChangeStatus:(PKWebSocketStatus)status;
+- (void)handler:(PKWebSocketHandler *)handler didFailWithError:(NSError *)error;
+
+- (void)handler:(PKWebSocketHandler *)handler didProcessMessage:(PKWebSocketMessage *)message error:(NSError *)error;
+- (void)handlerDidSendMessage;
+@end
@interface PKWebSocketHandler : NSObject <PKWebSocketFrameDelegate>
@property (nonatomic, strong, readwrite) PKWebSocketFrame *frame;
+@property (nonatomic, assign, readwrite) PKWebSocketStatus status;
@property (nonatomic, strong, readwrite) NSDictionary *tlsSettings;
@property (nonatomic, assign, readwrite) NSUInteger timeout;
@property (nonatomic, strong, readonly) PKWebSocketURL *url;
-@property (nonatomic, assign, readwrite) PKWebSocketStatus status;
-@property (nonatomic, weak, readwrite) PKWebSocket *websocket;
+
+@property (nonatomic, weak, readwrite) id<PKWebSocketHandlerDelegate> delegate;
#pragma mark - High level methods
- (BOOL)connectWithURL:(PKWebSocketURL *)anURL error:(NSError **)outError;
- (void)disconnect;
-- (void)sendMessage:(NSString *)aMessage;
-
-#pragma mark - Handshake frames
-
-- (BOOL)validateHandshakeResponse:(PKHTTPResponse *)response error:(NSError **)outError;
-- (PKHTTPRequest *)handshakeRequestWithURL:(PKWebSocketURL *)anURL error:(NSError **)outError;
+- (void)sendBinaryFrameWithData:(NSData *)data;
+- (void)sendTextFrameWithString:(NSString *)string;
+- (void)sendData:(NSData *)data tag:(long)tag;
#pragma mark - Handshake frames
@@ -47,3 +54,4 @@
- (NSData *)handshakeResponseFrameBoundary;
@end
+
View
173 PKWebSocket/Handlers/PKWebSocketHandler.m
@@ -7,18 +7,18 @@
//
#import "PKWebSocketHandler.h"
-#import "PKWebSocket.h"
-#import "PKWebSocketURL.h"
#import "AsyncSocket.h"
+#import "PKWebSocketURL.h"
#import "PKHTTPResponse.h"
#import "PKHTTPRequest.h"
#import "PKWebSocketFrame.h"
+#import "PKWebSocketMessage.h"
-NSString * const HTTP_GET_METHOD = @"GET";
-NSString * const HTTP_RESPONSE_BOUNDARY = @"\r\n\r\n";
-NSString * const HTTP_UPGRADE_HEADER = @"Upgrade";
-NSString * const HTTP_CONNECTION_HEADER = @"Connection";
+NSString * const HTTP_GET_METHOD = @"GET";
+NSString * const HTTP_RESPONSE_BOUNDARY = @"\r\n\r\n";
+NSString * const HTTP_UPGRADE_HEADER = @"Upgrade";
+NSString * const HTTP_CONNECTION_HEADER = @"Connection";
const NSUInteger HTTP_UPGRADE_STATUS_CODE = 101;
@interface PKWebSocketHandler ()
@@ -26,34 +26,41 @@ @interface PKWebSocketHandler ()
@property (nonatomic, strong, readonly) NSArray *runLoopModes;
@end
+
@implementation PKWebSocketHandler
// Public
-@synthesize frame = _frame;
+@synthesize frame = _frame;
+@synthesize timeout = _timeout;
@synthesize tlsSettings = _tlsSettings;
-@synthesize timeout = _timeout;
-@synthesize url = _url;
-@synthesize status = _status;
-@synthesize websocket;
+@synthesize status = _status;
+@synthesize url = _url;
+@synthesize delegate = _websocket;
// Private
-@synthesize socket = _socket;
+@synthesize socket = _socket;
@synthesize runLoopModes = _runLoopModes;
- (id)init {
self = [super init];
if (self != nil) {
- self->_socket = [[AsyncSocket alloc] initWithDelegate:self];
- self->_status = PKWebSocketDisconnectedStatus;
+ self.frame = nil;
+ self->_status = PKWebSocketDisconnectedStatus;
self->_runLoopModes = [NSArray arrayWithObject:NSRunLoopCommonModes];
- self.tlsSettings = nil;
- self.timeout = 5;
- self.frame = nil;
+ self.timeout = 5;
+ self.tlsSettings = nil;
+ self->_socket = [[AsyncSocket alloc] initWithDelegate:self];
}
return self;
}
+- (void)setStatus:(PKWebSocketStatus)aStatus {
+ if (self->_status == aStatus) return;
+ self->_status = aStatus;
+ [self.delegate handler:self didChangeStatus:self->_status];
+}
+
#pragma mark - Socket management
@@ -62,15 +69,14 @@ - (BOOL)connectWithURL:(PKWebSocketURL *)anURL error:(NSError **)outError {
self.status = PKWebSocketConnectingStatus;
- if ([anURL isSecure]) {
+ if ([anURL isSecure] && self.tlsSettings != nil) {
[self.socket startTLS:self.tlsSettings];
}
- NSError *error;
BOOL status = [self.socket connectToHost:anURL.host
onPort:[anURL.port intValue]
withTimeout:self.timeout
- error:&error];
+ error:outError];
if (status) {
self->_url = anURL;
if (self.runLoopModes) {
@@ -79,22 +85,60 @@ - (BOOL)connectWithURL:(PKWebSocketURL *)anURL error:(NSError **)outError {
return YES;
} else {
self.status = PKWebSocketDisconnectedStatus;
- if (outError != NULL) *outError = error;
return NO;
}
}
- (void)disconnect {
- // Initiate closing handshake
[self frame:self.frame initiateClosingHandshakeWithData:self.frame.closingPayload];
[self.socket disconnectAfterReadingAndWriting];
}
-- (void)sendMessage:(NSString *)aMessage {
- NSData *payload = [self.frame textFramePayloadWithString:aMessage];
- [self.socket writeData:payload
- withTimeout:self.timeout
- tag:PKWebSocketTagMessage];
+- (void)sendBinaryFrameWithData:(NSData *)aData {
+ NSData *payload = [self.frame binaryFramePayloadWithData:aData];
+ [self sendData:payload tag:PKWebSocketTagMessage];
+}
+
+- (void)sendTextFrameWithString:(NSString *)aString {
+ NSData *payload = [self.frame textFramePayloadWithString:aString];
+ [self sendData:payload tag:PKWebSocketTagMessage];
+}
+
+- (void)sendData:(NSData *)aData tag:(long)aTag {
+ [self.socket writeData:aData withTimeout:self.timeout tag:aTag];
+}
+
+
+#pragma mark - Handshake frames
+
+- (BOOL)validateHandshakeResponse:(PKHTTPResponse *)aResponse
+ error:(NSError **)outError {
+ BOOL valid = aResponse.statusCode == HTTP_UPGRADE_STATUS_CODE;
+ if (!valid) return NO;
+ valid = [aResponse valueForHTTPHeaderField:HTTP_UPGRADE_HEADER] != nil;
+ if (!valid) return NO;
+ valid = [aResponse valueForHTTPHeaderField:HTTP_CONNECTION_HEADER] != nil;
+ return valid;
+}
+
+- (PKHTTPRequest *)handshakeRequestWithURL:(PKWebSocketURL *)anURL
+ error:(NSError **)outError {
+ PKHTTPRequest *request = [[PKHTTPRequest alloc] initWithMethod:HTTP_GET_METHOD
+ URL:anURL];
+ [request addValue:@"WebSocket" forHTTPHeaderField:HTTP_UPGRADE_HEADER];
+ [request addValue:@"Upgrade" forHTTPHeaderField:HTTP_CONNECTION_HEADER];
+
+ NSString *host = [anURL hostForHTTPHeader];
+ [request addValue:host forHTTPHeaderField:@"Host"];
+
+ NSString *origin = [NSString stringWithFormat:@"http://%@", host];
+ [request addValue:origin forHTTPHeaderField:@"Origin"];
+
+ return request;
+}
+
+- (NSData *)handshakeResponseFrameBoundary {
+ return [HTTP_RESPONSE_BOUNDARY dataUsingEncoding:NSASCIIStringEncoding];
}
@@ -114,16 +158,15 @@ - (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UIn
self.status = PKWebSocketOpeningStatus;
PKHTTPRequest *request = [self handshakeRequestWithURL:self.url error:NULL];
- [self.socket writeData:[request asData]
- withTimeout:self.timeout
- tag:PKWebSocketTagOpeningHandshake];
+ [self sendData:[request asData] tag:PKWebSocketTagOpeningHandshake];
}
- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)outError {
if (self.status == PKWebSocketOpenedStatus) {
- [self.websocket _dispatchClosed];
+ self.status = PKWebSocketClosedStatus;
} else {
- [self.websocket _dispatchFailure:[NSNumber numberWithInt:1]];
+ NSLog(@"");
+ //[self.delegate _dispatchFailure:[NSNumber numberWithInt:1]];
}
}
@@ -131,17 +174,13 @@ - (void)onSocketDidDisconnect:(AsyncSocket *)sock {
self.status = PKWebSocketDisconnectedStatus;
}
-- (void)onSocketDidSecure:(AsyncSocket *)sock {
- [self.websocket _dispatchSecured];
-}
-
- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag {
if (tag == PKWebSocketTagOpeningHandshake) {
[sock readDataToData:[self handshakeResponseFrameBoundary]
withTimeout:self.timeout
tag:PKWebSocketTagOpeningHandshake];
} else if (tag == PKWebSocketTagMessage) {
- [self.websocket _dispatchMessageSent];
+ [self.delegate handlerDidSendMessage];
} else {
// Closing handshake probably
}
@@ -153,17 +192,19 @@ - (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)ta
if ([self validateHandshakeResponse:response error:NULL]) {
self.status = PKWebSocketOpenedStatus;
- [self.websocket _dispatchOpened];
[sock readDataWithTimeout:-1 tag:PKWebSocketTagMessage];
} else {
- [self.websocket _dispatchFailure:[NSNumber numberWithInt:PKWebSocketErrorHandshakeFailed]];
+ // Handshake error
+ [self.delegate handler:self didFailWithError:nil];
[self disconnect];
}
} else if (tag == PKWebSocketTagMessage) {
[self.frame processData:data];
[sock readDataWithTimeout:-1 tag:PKWebSocketTagMessage];
+ } else if (tag == PKWebSocketTagClosingHandshake) {
+ // Closing handshake
} else {
- // Closing handshake probably
+ NSAssert(nil, @"Unknown tag (%d) received!", tag);
}
}
@@ -184,53 +225,27 @@ - (void)frame:(PKWebSocketFrame *)frame readDataOfLength:(NSUInteger)length {
- (void)frame:(PKWebSocketFrame *)frame initiateClosingHandshakeWithData:(NSData *)data {
if (data == nil && [data length] == 0) return;
- [self.socket writeData:data
- withTimeout:self.timeout
- tag:PKWebSocketTagClosingHandshake];
+ [self sendData:data tag:PKWebSocketTagClosingHandshake];
}
- (void)frame:(PKWebSocketFrame *)frame didProcessData:(NSData *)data error:(NSError *)error {
+ if (data == nil) {
+ [self.delegate handler:self didFailWithError:error];
+ return;
+ }
+ PKWebSocketMessage *message = [PKWebSocketMessage messageWithData:data];
+ [self.delegate handler:self didProcessMessage:message error:error];
}
- (void)frame:(PKWebSocketFrame *)frame didProcessString:(NSString *)string error:(NSError *)error {
- if (string != nil) {
- [self.websocket _dispatchMessageReceived:string];
- } else {
- [self.websocket _dispatchFailure:[NSNumber numberWithInt:1]];
+ if (string == nil) {
+ [self.delegate handler:self didFailWithError:error];
+ return;
}
-}
-
-
-#pragma mark - Handshake frames
-
-- (BOOL)validateHandshakeResponse:(PKHTTPResponse *)aResponse error:(NSError **)outError {
- BOOL valid = aResponse.statusCode == HTTP_UPGRADE_STATUS_CODE;
- if (!valid) return NO;
- valid = [aResponse valueForHTTPHeaderField:HTTP_UPGRADE_HEADER] != nil;
- if (!valid) return NO;
- valid = [aResponse valueForHTTPHeaderField:HTTP_CONNECTION_HEADER] != nil;
- return valid;
-}
-
-- (PKHTTPRequest *)handshakeRequestWithURL:(PKWebSocketURL *)anURL
- error:(NSError **)outError {
- PKHTTPRequest *request = [[PKHTTPRequest alloc] initWithMethod:HTTP_GET_METHOD
- URL:anURL];
- [request addValue:@"WebSocket" forHTTPHeaderField:HTTP_UPGRADE_HEADER];
- [request addValue:@"Upgrade" forHTTPHeaderField:HTTP_CONNECTION_HEADER];
-
- NSString *host = [anURL hostForHTTPHeader];
- [request addValue:host forHTTPHeaderField:@"Host"];
-
- NSString *origin = [NSString stringWithFormat:@"http://%@", host];
- [request addValue:origin forHTTPHeaderField:@"Origin"];
-
- return request;
-}
-
-- (NSData *)handshakeResponseFrameBoundary {
- return [HTTP_RESPONSE_BOUNDARY dataUsingEncoding:NSASCIIStringEncoding];
+ PKWebSocketMessage *message = [PKWebSocketMessage messageWithString:string];
+ [self.delegate handler:self didProcessMessage:message error:error];
}
@end
+
View
39 PKWebSocket/PKWebSocket.h
@@ -11,33 +11,38 @@
#import <Foundation/Foundation.h>
#import "PKWebSocketConstants.h"
-#import "PKWebSocketDelegate.h"
#import "PKWebSocketHandler.h"
-#import "PKWebSocketURL.h"
+@class PKWebSocket;
+@class PKWebSocketHandler;
+@class PKWebSocketURL;
+@class PKWebSocketMessage;
-@interface PKWebSocket : NSObject
-@property (nonatomic, weak, readwrite) id<PKWebSocketDelegate> delegate;
+@protocol PKWebSocketDelegate <NSObject>
+- (void)webSocketDidOpen:(PKWebSocket *)webSocket;
+- (void)webSocketDidClose:(PKWebSocket *)webSocket;
+- (void)webSocket:(PKWebSocket *)webSocket didFailWithError:(NSError *)error;
+- (void)webSocket:(PKWebSocket *)webSocket didReceiveMessage:(PKWebSocketMessage *)message;
+
+@optional
+- (void)webSocketDidSendMessage:(PKWebSocket *)webSocket;
+@end
+
+@interface PKWebSocket : NSObject <PKWebSocketHandlerDelegate>
+
+@property (nonatomic, weak, readwrite) id<PKWebSocketDelegate> delegate;
@property (nonatomic, strong, readwrite) PKWebSocketHandler *handler;
-@property (nonatomic, strong, readonly) PKWebSocketURL *url;
-- (id)initWithURLString:(NSString *)URLString
- handler:(PKWebSocketHandler *)handler
- delegate:(id<PKWebSocketDelegate>)delegate;
+- (id)initWithHandler:(PKWebSocketHandler *)handler
+ delegate:(id<PKWebSocketDelegate>)delegate;
-- (BOOL)openWithError:(NSError **)outError;
- (void)close;
-- (void)send:(NSString *)message;
+- (BOOL)openWithURLString:(NSString *)url error:(NSError **)error;
+- (void)send:(PKWebSocketMessage *)message;
- (void)setTLSSettings:(NSDictionary *)settings;
- (NSDictionary *)TLSSettings;
-
--(void)_dispatchFailure:(NSNumber*)code;
--(void)_dispatchClosed;
--(void)_dispatchOpened;
--(void)_dispatchMessageReceived:(NSString*)message;
--(void)_dispatchMessageSent;
-- (void)_dispatchSecured;
+- (PKWebSocketURL *)url;
@end
View
79 PKWebSocket/PKWebSocket.m
@@ -10,34 +10,30 @@
//
#import "PKWebSocket.h"
-#import "AsyncSocket.h"
#import "PKWebSocketHandler.h"
#import "PKHTTPRequest.h"
#import "PKHTTPResponse.h"
+#import "PKWebSocketMessage.h"
+#import "PKWebSocketURL.h"
@implementation PKWebSocket
-// Public
@synthesize delegate = _delegate;
-@synthesize handler = _handler;
-@synthesize url = _url;
+@synthesize handler = _handler;
#pragma mark - Initializers
-- (id)initWithURLString:(NSString *)anURL
- handler:(PKWebSocketHandler *)aHandler
- delegate:(id<PKWebSocketDelegate>)aDelegate {
- NSParameterAssert(anURL);
+- (id)initWithHandler:(PKWebSocketHandler *)aHandler
+ delegate:(id<PKWebSocketDelegate>)aDelegate {
NSParameterAssert(aHandler);
self = [super init];
if (self != nil) {
- self->_url = [PKWebSocketURL URLWithString:anURL];
- self.handler = aHandler;
- self.handler.websocket = self;
+ self.handler = aHandler;
self.delegate = aDelegate;
+ self.handler.delegate = self;
}
return self;
}
@@ -49,14 +45,22 @@ - (void)close {
[self.handler disconnect];
}
-- (BOOL)openWithError:(NSError **)outError {
- return [self.handler connectWithURL:self.url error:outError];
+- (BOOL)openWithURLString:(NSString *)aURL error:(NSError **)outError {
+ PKWebSocketURL *url = [PKWebSocketURL URLWithString:aURL];
+ return [self.handler connectWithURL:url error:outError];
}
--(void)send:(NSString *)aMessage {
- [self.handler sendMessage:aMessage];
+- (void)send:(PKWebSocketMessage *)aMessage {
+ if ([aMessage isBinary]) {
+ [self.handler sendBinaryFrameWithData:aMessage.data];
+ } else {
+ [self.handler sendTextFrameWithString:aMessage.string];
+ }
}
+
+#pragma mark - Accessors
+
- (void)setTLSSettings:(NSDictionary *)aSettings {
self.handler.tlsSettings = aSettings;
}
@@ -65,44 +69,49 @@ - (NSDictionary *)TLSSettings {
return self.handler.tlsSettings;
}
+- (PKWebSocketURL *)url {
+ return self.handler.url;
+}
+
#pragma mark Delegate dispatch methods
--(void)_dispatchFailure:(NSNumber*)code {
- if(_delegate && [_delegate respondsToSelector:@selector(webSocket:didFailWithError:)]) {
- [_delegate webSocket:self didFailWithError:[NSError errorWithDomain:PKWebSocketErrorDomain code:[code intValue] userInfo:nil]];
+- (void)handler:(PKWebSocketHandler *)handler didChangeStatus:(PKWebSocketStatus)status {
+ if (_delegate == nil) return;
+
+ SEL sel;
+ switch (status) {
+ case PKWebSocketClosedStatus:
+ sel = @selector(webSocketDidClose:);
+ break;
+ case PKWebSocketOpenedStatus:
+ sel = @selector(webSocketDidOpen:);
+ break;
+ default:
+ sel = NULL;
+ break;
}
-}
-
--(void)_dispatchClosed {
- if (_delegate && [_delegate respondsToSelector:@selector(webSocketDidClose:)]) {
- [_delegate webSocketDidClose:self];
+ if (sel != NULL && [_delegate respondsToSelector:sel]) {
+ [_delegate performSelector:sel withObject:self];
}
}
--(void)_dispatchOpened {
- if (_delegate && [_delegate respondsToSelector:@selector(webSocketDidOpen:)]) {
- [_delegate webSocketDidOpen:self];
+- (void)handler:(PKWebSocketHandler *)handler didFailWithError:(NSError *)error {
+ if(_delegate && [_delegate respondsToSelector:@selector(webSocket:didFailWithError:)]) {
+ [_delegate webSocket:self didFailWithError:error];
}
}
--(void)_dispatchMessageReceived:(NSString*)message {
+- (void)handler:(PKWebSocketHandler *)handler didProcessMessage:(PKWebSocketMessage *)message error:(NSError *)error {
if (_delegate && [_delegate respondsToSelector:@selector(webSocket:didReceiveMessage:)]) {
[_delegate webSocket:self didReceiveMessage:message];
}
}
--(void)_dispatchMessageSent {
+- (void)handlerDidSendMessage {
if (_delegate && [_delegate respondsToSelector:@selector(webSocketDidSendMessage:)]) {
[_delegate webSocketDidSendMessage:self];
}
}
-- (void)_dispatchSecured {
- if (_delegate && [_delegate respondsToSelector:@selector(webSocketDidSecure:)]) {
- [_delegate webSocketDidSecure:self];
- }
-}
-
@end
-
View
2 PKWebSocket/PKWebSocketConstants.h
@@ -18,7 +18,7 @@ extern const NSUInteger PKWebSocketTagMessage;
typedef enum {
PKWebSocketDisconnectedStatus = 0,
PKWebSocketConnectingStatus,
- PKWebSocketconnectedStatus,
+ PKWebSocketConnectedStatus,
PKWebSocketOpeningStatus,
PKWebSocketOpenedStatus,
PKWebSocketClosingStatus,
View
22 PKWebSocket/PKWebSocketDelegate.h
@@ -1,22 +0,0 @@
-//
-// PKWebSocketDelegate.h
-// PKWebSocket
-//
-// Created by Pavel Kunc on 16/04/2012.
-// Copyright (c) 2012 Pavel Kunc. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-
-@class AsyncSocket;
-@class PKWebSocket;
-
-@protocol PKWebSocketDelegate <NSObject>
-@optional
-- (void)webSocket:(PKWebSocket *)webSocket didFailWithError:(NSError *)error;
-- (void)webSocketDidOpen:(PKWebSocket *)webSocket;
-- (void)webSocketDidClose:(PKWebSocket *)webSocket;
-- (void)webSocket:(PKWebSocket *)webSocket didReceiveMessage:(NSString *)message;
-- (void)webSocketDidSendMessage:(PKWebSocket *)webSocket;
-- (void)webSocketDidSecure:(PKWebSocket *)webSocket;
-@end
View
46 PKWebSocket/PKWebSocketHandlerProtocol.h
@@ -1,46 +0,0 @@
-//
-// PKWebSocketHandlerProtocol.h
-// PKWebSocket
-//
-// Created by Pavel Kunc on 17/04/2012.
-// Copyright (c) 2012 Pavel Kunc. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-
-@class PKHTTPRequest;
-@class PKHTTPResponse;
-@class AsyncSocket;
-@class PKWebSocketURL;
-
-@protocol PKWebSocketHandlerProtocol <NSObject>
-
-@optional
-
-#pragma mark - High level methods
-
-- (void)closeConnectionOnSocket:(AsyncSocket *)aSocket;
-- (BOOL)initiateHandshakdeOnSocket:(AsyncSocket *)aSocket error:(NSError **)outError;
-- (BOOL)readNextFrameOnSocket:(AsyncSocket *)aSocket error:(NSError **)outError;
-
-
-#pragma mark - Handshake frames
-
-- (BOOL)validateHandshakeResponse:(PKHTTPResponse *)response error:(NSError **)outError;
-- (PKHTTPRequest *)handshakeRequestWithURL:(PKWebSocketURL *)anURL error:(NSError **)outError;
-
-
-#pragma mark - Handshake frames
-
-- (BOOL)validateHandshakeResponse:(PKHTTPResponse *)response error:(NSError **)outError;
-- (PKHTTPRequest *)handshakeRequestWithURL:(PKWebSocketURL *)anURL error:(NSError **)outError;
-- (NSData *)handshakeResponseFrameBoundary;
-
-
-#pragma mark - String frames
-
-- (NSString *)stringWithFrame:(NSData *)aFrame error:(NSError **)outError;
-- (NSData *)frameWithString:(NSString *)aString error:(NSError **)outError;
-- (BOOL)isValidStringFrame:(NSData *)aFrame;
-
-@end
View
30 PKWebSocket/PKWebSocketMessage.h
@@ -0,0 +1,30 @@
+//
+// PKWebSocketMessage.h
+// PKWebSocket
+//
+// Created by Pavel Kunc on 22/04/2012.
+// Copyright (c) 2012 Pavel Kunc. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+typedef enum {
+ PKWebSocketMessageTypeText = 1,
+ PKWebSocketMessageTypeData
+} PKWebSocketMessageType;
+
+@interface PKWebSocketMessage : NSObject
+
+@property (nonatomic, strong, readwrite) NSData *data;
+@property (nonatomic, strong, readwrite) NSString *string;
+@property (nonatomic, assign, readwrite) PKWebSocketMessageType type;
+
++ (id)messageWithData:(NSData *)data;
++ (id)messageWithString:(NSString *)string;
+
+- (id)initWithContent:(id)content type:(PKWebSocketMessageType)type;
+
+- (BOOL)isBinary;
+
+@end
+
View
43 PKWebSocket/PKWebSocketMessage.m
@@ -0,0 +1,43 @@
+//
+// PKWebSocketMessage.m
+// PKWebSocket
+//
+// Created by Pavel Kunc on 22/04/2012.
+// Copyright (c) 2012 Pavel Kunc. All rights reserved.
+//
+
+#import "PKWebSocketMessage.h"
+
+@implementation PKWebSocketMessage
+
+@synthesize data = _data;
+@synthesize string = _string;
+@synthesize type = _type;
+
++ (id)messageWithData:(NSData *)data {
+ return [[[self class] alloc] initWithContent:data type:PKWebSocketMessageTypeData];
+}
+
++ (id)messageWithString:(NSString *)string {
+ return [[[self class] alloc] initWithContent:string type:PKWebSocketMessageTypeText];
+}
+
+- (id)initWithContent:(id)aContent type:(PKWebSocketMessageType)aType {
+ self = [super init];
+ if (self != nil) {
+ self->_type = aType;
+ if (aType == PKWebSocketMessageTypeData) {
+ self->_data = aContent;
+ } else {
+ self->_string = aContent;
+ }
+ }
+ return self;
+}
+
+- (BOOL)isBinary {
+ return _type == PKWebSocketMessageTypeData;
+}
+
+@end
+
View
18 PKWebSocketTests/Frames/PKWebSocketFrame-Hixie76Tests.m
@@ -60,6 +60,11 @@ - (NSData *)dataWithInvalidFrame {
return [NSData dataWithBytes:"\xe1\x65\x6C\x6C\x6F\xFF" length:6];
}
+- (NSData *)dataWithNotClosedFrame {
+ // Frame: START|á|e|l|l|o
+ return [NSData dataWithBytes:"\x00\xe1\x65\x6C\x6C\x6F" length:6];
+}
+
#pragma mark - PKWebSocketFrameDelegate
@@ -73,8 +78,8 @@ - (void)frame:(PKWebSocketFrame *)frame didProcessString:(NSString *)string erro
if (string) {
STAssertEqualObjects(string, _expectedString, nil);
} else {
+ NSLog(@"Error: %@", [error localizedDescription]);
STAssertNil(string, nil);
- //STAssertTrue();
}
}
@@ -127,6 +132,17 @@ - (void)testProcessInvalidFrameCorrectly {
//[delegateMock verify];
}
+- (void)testProcessNotClosedFrameCorrectly {
+ //id delegateMock = [OCMockObject partialMockForObject:self];
+ PKWebSocketFrameHixie76 *frame = [[PKWebSocketFrameHixie76 alloc] init];
+ [frame setDelegate:self];
+
+ //[[delegateMock expect] frame:frame didProcessString:@"HelloPlain" error:nil];
+ _expectedString = nil;
+ [frame processData:[self dataWithNotClosedFrame]];
+ //[delegateMock verify];
+}
+
- (void)testProcessClosingFrameCorrectly {
//id delegateMock = [OCMockObject partialMockForObject:self];
PKWebSocketFrameHixie76 *frame = [[PKWebSocketFrameHixie76 alloc] init];
View
22 PKWebSocketTests/PKWebSocketTests.m
@@ -9,6 +9,7 @@
#import <Foundation/Foundation.h>
#import <SenTestingKit/SenTestingKit.h>
#import "PKWebSocket.h"
+#import "PKWebSocketMessage.h"
#import "PKWebSocketHandler-Hixie76.h"
@interface PKWebSocketTests : SenTestCase <PKWebSocketDelegate>
@@ -33,8 +34,8 @@ - (void)tearDown {
}
- (NSString *)standardURL {
- //return @"ws://echo.websocket.org";
- return @"ws://localhost:10000";
+ return @"ws://echo.websocket.org";
+ //return @"ws://localhost:10000";
}
- (NSString *)secureURL {
@@ -47,21 +48,21 @@ - (void)webSocket:(PKWebSocket *)webSocket didFailWithError:(NSError *)error {
}
- (void)webSocketDidOpen:(PKWebSocket *)webSocket {
- [webSocket send:@"Ping-Pong"];
+ [webSocket send:[PKWebSocketMessage messageWithString:@"Ping-Pong"]];
}
-- (void)webSocket:(PKWebSocket *)webSocket didReceiveMessage:(NSString *)message {
+- (void)webSocketDidClose:(PKWebSocket *)webSocket {}
+
+- (void)webSocket:(PKWebSocket *)webSocket didReceiveMessage:(PKWebSocketMessage *)message {
_finished = YES;
- STAssertEqualObjects(@"Ping-Pong",message, nil);
+ STAssertEqualObjects(@"Ping-Pong", message.string, nil);
}
-/*
+
- (void)testTestStandardConnectionShouldBeSuccessful {
NSError *error;
- PKWebSocket *ws = [[PKWebSocket alloc] initWithURLString:[self standardURL]
- handler:_handler
- delegate:self];
- STAssertTrue([ws openWithError:&error],nil);
+ PKWebSocket *ws = [[PKWebSocket alloc] initWithHandler:_handler delegate:self];
+ STAssertTrue([ws openWithURLString:[self standardURL] error:&error],nil);
NSRunLoop *theRL = [NSRunLoop currentRunLoop];
// Begin a run loop terminated when the downloadComplete it set to true
@@ -69,6 +70,7 @@ - (void)testTestStandardConnectionShouldBeSuccessful {
while (!_finished && [theRL runMode:NSDefaultRunLoopMode beforeDate:date]);
}
+/*
- (void)testTestSecureConnectionShouldBeSuccessful {
NSMutableDictionary *tlsSettings = [NSMutableDictionary dictionaryWithCapacity:4];
[tlsSettings setObject:@"echo.websocket.org" forKey:(NSString *)kCFStreamSSLPeerName];
View
1 PKWebSocketTests/Servers/.rvmrc
@@ -0,0 +1 @@
+rvm 1.9.3-p0@pkwebsocket
View
5 PKWebSocketTests/Servers/Gemfile
@@ -0,0 +1,5 @@
+source :rubygems
+
+gem "em-websocket"
+gem "em-http-request"
+
View
20 PKWebSocketTests/Servers/Gemfile.lock
@@ -0,0 +1,20 @@
+GEM
+ remote: http://rubygems.org/
+ specs:
+ addressable (2.2.7)
+ em-http-request (0.3.0)
+ addressable (>= 2.0.0)
+ escape_utils
+ eventmachine (>= 0.12.9)
+ em-websocket (0.3.6)
+ addressable (>= 2.1.1)
+ eventmachine (>= 0.12.9)
+ escape_utils (0.2.4)
+ eventmachine (0.12.10)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ em-http-request
+ em-websocket
View
35 PKWebSocketTests/Servers/em-websocket-secure.rb
@@ -0,0 +1,35 @@
+require 'em-websocket'
+
+EventMachine.run {
+ @channel = EM::Channel.new
+
+ options = {
+ :host => "0.0.0.0",
+ :port => 10_000,
+ :secure => true,
+ :debug => true,
+ :tls_options => {
+ :private_key_file => "./tsl-private-key",
+ :cert_chain_file => "./tsl-cert.crt"
+ }
+ }
+
+ EventMachine::WebSocket.start(options) do |ws|
+ ws.onopen {
+ @sid = @channel.subscribe {|msg| ws.send(msg) }
+ puts "Client #{@sid} connected!"
+ }
+
+ ws.onmessage {|data|
+ @channel.push(data)
+ }
+
+ ws.onclose {
+ puts "Client #{@sid} gone..."
+ @channel.unsubscribe(@sid)
+ }
+ end
+
+ puts "Server started"
+}
+
View
30 PKWebSocketTests/Servers/em-websocket.rb
@@ -0,0 +1,30 @@
+require 'em-websocket'
+
+EventMachine.run {
+ @channel = EM::Channel.new
+
+ options = {
+ :host => "0.0.0.0",
+ :port => 10_000,
+ :debug => true
+ }
+
+ EventMachine::WebSocket.start(options) do |ws|
+ ws.onopen {
+ @sid = @channel.subscribe {|msg| ws.send(msg) }
+ puts "Client #{@sid} connected!"
+ }
+
+ ws.onmessage {|data|
+ @channel.push(data)
+ }
+
+ ws.onclose {
+ puts "Client #{@sid} gone..."
+ @channel.unsubscribe(@sid)
+ }
+ end
+
+ puts "Server started"
+}
+

0 comments on commit 8d1d978

Please sign in to comment.
Something went wrong with that request. Please try again.