Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
WebSocket client for Cocoa
Objective-C C Ruby JavaScript
Tree: 30d5f0f042

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.
PKWebSocket.xcodeproj
PKWebSocket
PKWebSocketTests
Submodules
Vendor/OCMock-2.0
.gitignore
.gitmodules
README.md

README.md

PKWebSocket / WebSocket client for Cocoa

Implementation of the WebSocket protocol on top of the CocoaAsyncSocket for Cocoa. I used Zimt and cocoa-websocket project as basic for the this re-implementation.

I wanted to support multiple versions of the WebSocket protocol, make possible to easily add new protocol versions and to be able to influence handshake requests and so on.

Project is done as Static library which makes it usable in ARC/Non-ARC environments.

Architecture

I follow the terms in the specification to divide project in to the three layers.

1) High-level public API defined in the PKWebSocket. At this layer you work with the messages which you send and receive. PKWebSocketMessage is an envelope object to be possible add binary messages for the RFC6455 version of the protocol.

All API at this layer is PUBLIC.

2) Handlers layer where handshakes & frames are handled and translated to messaeges. Also socket connection is here to read/write frames.

All API at this layer is PRIVATE.

3) Frames layer implements actual parsing of the raw data from sockets. Validates frames and sends them to the Handler layer.

All API at this layer is PRIVATE.

Utilities

There are few utility classes:

  • PKHTTPResponse - encapsulate HTTP response
  • PKHTTPRequest - encapsulate HTTP request
  • PKWebSocketURL - NSURL sub-class making sure of correct parsing WebSocket URLs
  • PKWebSocketMessage - Wrapper around Data or String for compatibility
  • Crypto & Base64 categories

Extensibility

In order to add new protocol version there are 2 classes to implement.

If version introduce new handshake (opening/closing) a sub-class of the PKWebSocketHandler class is necessary You only need to override handshake frame methods:

- (BOOL)validateHandshakeResponse:(PKHTTPResponse *)response error:(NSError **)outError;
- (PKHTTPRequest *)handshakeRequestWithURL:(PKWebSocketURL *)anURL error:(NSError **)outError;
- (NSData *)handshakeResponseFrameBoundary;

You can add headers to your handshake request and validate your handshake response by overriding the appropriate methods.

If version introduce new framing you need to implement that framing in new PKWebSocketFrame sub-class. You should override init method and especially methods:

- (void)processData:(NSData *)data;
- (NSData *)textFramePayloadWithString:(NSString *)string;
- (NSData *)binaryFramePayloadWithData:(NSData *)aData;

Compatibility

Following WebSocket protocol versions are currently supported. Also I've tested on the following servers.

Protocols

  • Hixie 75 (Full support)
  • Hixie 76 (Full support)
  • TODO - RFC6455 (WIP - framing needs to be done)

Servers

  • em-websocket
  • ws://echo.websocket.org
  • TODO - Socket.IO & Node.js

Usage

#import "PKWebSocket.h"
#import "PKWebSocketMessage.h"
#import "PKWebSocketHandler-Hixie76.h"

NSString *url = @"ws://echo.websocket.org";
PKWebSocketHandlerHixie76 *handler = [[PKWebSocketHandlerHixie76 alloc] init];
PKWebSocket *ws = [[PKWebSocket alloc] initWithHandler:handler
                                              delegate:self];
NSError *error;
if ([ws openWithURLString:url error:&error]) {
  [ws send:[PKWebSocketMessage messageWithString:@"string to send"]];
  ...
  ...
}

Delegate methods

On the delegate WebSocket calls following methods if you opt for them:

- (void)webSocket:(PKWebSocket *)webSocket didFailWithError:(NSError *)error;
- (void)webSocketDidOpen:(PKWebSocket *)webSocket;
- (void)webSocketDidClose:(PKWebSocket *)webSocket;
- (void)webSocket:(PKWebSocket *)webSocket didReceiveMessage:(PKWebSocketMessage *)message;
- (void)webSocketDidSendMessage:(PKWebSocket *)webSocket;

Using secure WebSocket

In order to use secure WebSocket you need to use wss URL scheme and you will probably need to set some TLS settings.

NSMutableDictionary *tlsSettings = [NSMutableDictionary dictionaryWithCapacity:4];
[tlsSettings setObject:url.host forKey:(NSString *)kCFStreamSSLPeerName];

// Allow expired certificates
[tlsSettings setObject:[NSNumber numberWithBool:YES]
                forKey:(NSString *)kCFStreamSSLAllowsExpiredCertificates];

// Allow self-signed certificates
[tlsSettings setObject:[NSNumber numberWithBool:YES]
                forKey:(NSString *)kCFStreamSSLAllowsAnyRoot];

// In fact, don't even validate the certificate chain
[tlsSettings setObject:[NSNumber numberWithBool:NO]
                forKey:(NSString *)kCFStreamSSLValidatesCertificateChain];

// Set it to the web socket
[websocket setTLSSetting:tlsSettings];

Requirements & Dependencies & Submodules

Get code & Contribute

TOWRITE

Code

If you have GIT 1.7+ ...

git clone git@github.com:pk/PKWebSocket.git --recursive

or, earlier...

git clone git@github.com:pk/PKWebSocket.git
cd PKWebSocket
git submodule init
git submodule update

Test suite

TOWRITE

Adding to your project

You can add PKWebSocket to your project in two ways:

XCode 4.x sub-project

Get the static library binary release (TODO)

Based on

Something went wrong with that request. Please try again.