GithubHelp home page GithubHelp logo

zwopple / pocketsocket Goto Github PK

View Code? Open in Web Editor NEW
412.0 15.0 128.0 5.25 MB

Objective-C websocket library for building things that work in realtime on iOS and OS X.

License: Other

Objective-C 98.68% Ruby 1.32%

pocketsocket's Introduction

PocketSocket

Objective-C websocket library for building things that work in realtime on iOS and OS X.

Features

  • Conforms fully to RFC6455 websocket protocol
  • Support for websocket compression via the permessage-deflate extension
  • Passes all ~519 Autobahn Client Tests & Server Tests with 100% compliance1
  • Client & Server modes (see notes below)
  • TLS/SSL support
  • Asynchronous IO
  • Standalone PSWebSocketDriver for easy “Bring your own” networking IO

1Some server tests are non-strict and drop connections earlier when receiving malformed WebSocket payloads.

Dependencies

  • CFNetworking.framework
  • Foundation.framework
  • Security.framework
  • libSystem.dylib
  • libz.dylib

Installation

Installation is recommended via cocoapods. Add pod 'PocketSocket' to your Podfile and run pod install.

Major Components

  • PSWebSocketDriver - Networkless driver to deal with the websocket protocol. It solely operates with parsing raw bytes into events and sending events as raw bytes.
  • PSWebSocket - Networking based socket around NSInputStream and NSOutputStream deals with ensuring a connection is maintained. Uses the PSWebSocketDriver internally on the input and output.
  • PSWebSocketServer - Networking based socket server around CFSocket. It creates one PSWebSocket instance per incoming request.

Using PSWebSocket as a client

The client supports both the ws and secure wss protocols. It will automatically negotiate the certificates for you from the certificate chain on the device it’s running. If you need custom SSL certificate support or pinning look at the webSocket:evaluateServerTrust: in PSWebSocketDelegate

The client will always request the server turn on compression via the permessage-deflate extension. If the server accepts the request it will be enabled for the entire duration of the connection and used on all messages.

If the initial NSURLRequest specifies a timeout greater than 0 the connection will timeout if it cannot open within that interval, otherwise it could wait forever depending on the system.

# import <PSWebSocket/PSWebSocket.h>

@interface AppDelegate() <PSWebSocketDelegate>

@property (nonatomic, strong) PSWebSocket *socket;

@end
@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    
    // create the NSURLRequest that will be sent as the handshake
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"wss://example.com"]];
    
    // create the socket and assign delegate
    self.socket = [PSWebSocket clientSocketWithRequest:request];
    self.socket.delegate = self;
    
    // open socket
    [self.socket open];
    
    return YES;
}

#pragma mark - PSWebSocketDelegate

- (void)webSocketDidOpen:(PSWebSocket *)webSocket {
    NSLog(@"The websocket handshake completed and is now open!");
    [webSocket send:@"Hello world!"];
}
- (void)webSocket:(PSWebSocket *)webSocket didReceiveMessage:(id)message {
    NSLog(@"The websocket received a message: %@", message);
}
- (void)webSocket:(PSWebSocket *)webSocket didFailWithError:(NSError *)error {
    NSLog(@"The websocket handshake/connection failed with an error: %@", error);
}
- (void)webSocket:(PSWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean {
    NSLog(@"The websocket closed with code: %@, reason: %@, wasClean: %@", @(code), reason, (wasClean) ? @"YES" : @"NO");
}

@end

Using PSWebSocket via PSWebSocketServer

The server currently only supports the ws protocol. The server binds to the host address and port specified and accepts incoming connections. It parses the first HTTP request in each connection and then asks the delegate whether or not to accept it and complete the websocket handshake. The server expects to remain the delegate of all PSWebSocket instances it manages so be careful not to manage them yourself or detach them from the server.

# import <PSWebSocket/PSWebSocketServer.h>

@interface AppDelegate() <PSWebSocketServerDelegate>

@property (nonatomic, strong) PSWebSocketServer *server;

@end
@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)notification {
    _server = [PSWebSocketServer serverWithHost:nil port:9001];
    _server.delegate = self;
    [_server start];
}

#pragma mark - PSWebSocketServerDelegate

- (void)serverDidStart:(PSWebSocketServer *)server {
    NSLog(@"Server did start…");
}
- (void)serverDidStop:(PSWebSocketServer *)server {
    NSLog(@"Server did stop…");
}
- (BOOL)server:(PSWebSocketServer *)server acceptWebSocketWithRequest:(NSURLRequest *)request {
    NSLog(@"Server should accept request: %@", request);
    return YES;
}
- (void)server:(PSWebSocketServer *)server webSocket:(PSWebSocket *)webSocket didReceiveMessage:(id)message {
    NSLog(@"Server websocket did receive message: %@", message);
}
- (void)server:(PSWebSocketServer *)server webSocketDidOpen:(PSWebSocket *)webSocket {
    NSLog(@"Server websocket did open");
}
- (void)server:(PSWebSocketServer *)server webSocket:(PSWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean {
    NSLog(@"Server websocket did close with code: %@, reason: %@, wasClean: %@", @(code), reason, @(wasClean));
}
- (void)server:(PSWebSocketServer *)server webSocket:(PSWebSocket *)webSocket didFailWithError:(NSError *)error {
    NSLog(@"Server websocket did fail with error: %@", error);
}

@end

Using PSWebSocketDriver

The driver is the core of PSWebSocket. It deals with the handshake request/response lifecycle, packing messages into websocket frames to be sent over the wire and parsing websocket frames received over the wire.

It supports both client and server mode and has an identical API for each.

To create an instance of it you use either clientDriverWithRequest: or serverDriverWithRequest: in the client mode you are to pass in a NSURLRequest that will be sent as a handshake request. In server mode you are to pass in the NSURLRequest that was the handshake request.

Beyond that have a look at the PSWebSocketDriverDelegate methods and the simple API for interacting with the driver.

Roadmap

  • Examples, examples, examples!

Running Tests

  1. Install autobahntestsuite sudo pip install autobahntestsuite
  2. Start autobahn test server wstest -m fuzzingserver
  3. Run tests in Xcode

Why a new library?

Currently for Objective-C there is few options for websocket clients. SocketRocket, while probably the most notable, has a code base being entirely contained in a single file and proved difficult to build in new features such as permessage-deflate and connection timeouts.

PocketSocket firstly aims to provide a rich set of tools that are easy to dig into and modify when necessary. The decoupling of the network layer from the driver layer allows a lot of flexibility to incorporate the library with existing setups.

Secondly we intend on keeping PocketSocket at the top of it's game. As soon as any major websocket extensions come into play you can count on them being incorporated as soon as the drafts begin to stabalize.

Lastly we're set out to create the full picture from client to server all in a single, but decoupled toolkit for all use cases on iOS and OS X.

Authors

  • Robert Payne (@robertjpayne)

Contributors

  • Jens Alfke (@snej)

License

Copyright 2014-Present Zwopple Limited

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

pocketsocket's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pocketsocket's Issues

Expose the underlying request in PSWebSocket

I have the following workflow in my system:

  • Only two (different) clients, each connecting to their specific URL on the server.
  • Server accepts only sockets to these two URLs, rejecting everything else.

In my server's webSocketDidOpen delegate callback, I want to save these client sockets (to be able to send messages from the server to my clients). How do I distinguish between them, given that _request is a private property? Is there a better way than just exposing it to the public?

Support for HTTP proxy configuration

First of all, thank you for a great library. It works great in our iOS app!

Now, we have been contacted by a user who is unable to connect on their iPad. They use an HTTP proxy (settings entered globally under the system Settings/Wi-Fi).

Does PocketSocket respect/use the global iOS HTTP proxy settings? If not, is it possible to make PocketSocket use a proxy in some other way?

Not working with Firefox client

Firefox sends the a header with the "Connection" "keep-alive, Upgrade", which does not pass:
+ (BOOL)isWebSocketRequest:(NSURLRequest *)request

from PSWebSocketDriver.m
The problem is at line (line 87):
[[headers[@"Connection"] lowercaseString] isEqualToString:@"upgrade"]

After replacing it with
[[headers[@"Connection"] lowercaseString] containsString:@"upgrade"]
or
[[[[headers[@"Connection"] lowercaseString] stringByReplacingOccurrencesOfString:@" " withString:@""] componentsSeparatedByString:@","] containsObject:@"upgrade"]

the WebSocket opens and then fails with error :

Error Domain=PSWebSocketErrorDomain Code=3 "Output stream end encountered" UserInfo={NSLocalizedDescription=Output stream end encountered}

but the stream is actually of class NSInputStream.

Can anyone provide some suggestions?

WS Secure server: CFNetwork SSLHandshake failed (-9806)

Hi,

I'm having problems configuring a secure websocket server with PocketSocket.
The situation is the following: my app creates a websocket server listening on localhost, using a self-signed certificate I made with localhost as CN. The server is created without problems.
Another part of my app tries to connect to this websocket server from a webview. Unfortunately, when this happens, the error "CFNetwork SSLHandshake failed (-9806)" gets printed on the console, and the websocket isn't opened.
If the websocket is created without a certificate, an un-secure connection can be correctly created, but this isn't enough for my use case.
I tried adding the following parameter:
opts[(__bridge id)kCFStreamSSLLevel] = (__bridge id _Nullable)(kCFStreamSocketSecurityLevelSSLv2);
inside the - (void)accept:(CFSocketNativeHandle)handle method of PSWebSocketServer class, but this seems ineffective.
Also tried to disable App Transport Security in my app, and to allow exceptions such as NSTemporaryExceptionMinimumTLSVersion to it for the domains interested in this process (localhost, and the one the page in the webview is loaded from), with no success.
Do you have and idea about why the SSL handshake with the websocket server may fail?

Thanks!

'Server mode should have already opened streams.'

On PocketSocket version 1.0.1, OS X 10.11.6 (15G31), Xcode Version 7.3.1 (7D1014), Safari 9.1.2 (11601.7.7) I have got this error:

Server mode should have already opened streams.
2016-08-24 01:01:32.906 MyApp[4222:219540] (
    0   CoreFoundation                      0x00007fff8f4d84f2 __exceptionPreprocess + 178
    1   libobjc.A.dylib                     0x00007fffa0eb8f7e objc_exception_throw + 48
    2   CoreFoundation                      0x00007fff8f53f4bd +[NSException raise:format:] + 205
    3   MyApp                              0x000000010001a3a9 -[PSWebSocket stream:handleEvent:] + 233
    4   MyApp                              0x000000010002a021 __40-[PSWebSocketServer stream:handleEvent:]_block_invoke + 161
    5   libdispatch.dylib                   0x0000000100218070 _dispatch_call_block_and_release + 12
    6   libdispatch.dylib                   0x000000010020acc5 _dispatch_client_callout + 8
    7   libdispatch.dylib                   0x0000000100210112 _dispatch_queue_drain + 351
    8   libdispatch.dylib                   0x0000000100217e24 _dispatch_queue_invoke + 557
    9   libdispatch.dylib                   0x000000010020edab _dispatch_root_queue_drain + 1226
    10  libdispatch.dylib                   0x000000010020e8a5 _dispatch_worker_thread3 + 106
    11  libsystem_pthread.dylib             0x000000010026d336 _pthread_wqthread + 1129
    12  libsystem_pthread.dylib             0x000000010026af91 start_wqthread + 13
)
2016-08-24 01:01:32.906 MyApp[4222:219540] *** Terminating app due to uncaught exception 'Invalid State', reason: 'Server mode should have already opened streams.'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff8f4d84f2 __exceptionPreprocess + 178
    1   libobjc.A.dylib                     0x00007fffa0eb8f7e objc_exception_throw + 48
    2   CoreFoundation                      0x00007fff8f53f4bd +[NSException raise:format:] + 205
    3   MyApp                              0x000000010001a3a9 -[PSWebSocket stream:handleEvent:] + 233
    4   MyApp                              0x000000010002a021 __40-[PSWebSocketServer stream:handleEvent:]_block_invoke + 161
    5   libdispatch.dylib                   0x0000000100218070 _dispatch_call_block_and_release + 12
    6   libdispatch.dylib                   0x000000010020acc5 _dispatch_client_callout + 8
    7   libdispatch.dylib                   0x0000000100210112 _dispatch_queue_drain + 351
    8   libdispatch.dylib                   0x0000000100217e24 _dispatch_queue_invoke + 557
    9   libdispatch.dylib                   0x000000010020edab _dispatch_root_queue_drain + 1226
    10  libdispatch.dylib                   0x000000010020e8a5 _dispatch_worker_thread3 + 106
    11  libsystem_pthread.dylib             0x000000010026d336 _pthread_wqthread + 1129
    12  libsystem_pthread.dylib             0x000000010026af91 start_wqthread + 13
)
libc++abi.dylib: terminating with uncaught exception of type NSException

tvOS Support

Hi, I wanted to check whether tvOS has been tested/supported?

dispatch_async (bad access)

Hello, I have a bad access error for dispatch_async in 'executeWork'

Tracing it back to where the execute in '(void)open'

- (void)open {
    [self executeWork:^{
        if(_opened || _readyState != PSWebSocketReadyStateConnecting) {
            [NSException raise:@"Invalid State" format:@"You cannot open a PSWebSocket more than once."];
            return;
        }

        _opened = YES;

        // connect
        [self connect];
    }];
}

............
- (void)executeWork:(void (^)(void))work {
    NSParameterAssert(work);
    dispatch_async(_workQueue, work); <---- Error here
}

Is there any way to fix this? Not really sure why this happens...

Xcode Beta 6,
Building for IOS 7/8
Using swift with Object-C

Capitalize system library in podspec

Building this pod will fail if someone is using a case sensitive OS.

system should be capitalised:

ss.libraries = 'z', 'System'

otherwise you will run into: ld: library not found for -lsystem

Support for HTTP redirects

The client handshake handler doesn't recognize or follow an HTTP redirect response (301, 302 or 307).

Looks like the right place to fix this is in -[PSWebSocketDriver readBytes:maxLength:error:], under the comment "// validate status".

support connection timeout?

When the server or client out get out of network, the other side does not know. It take too long to know the disconnection. can I setup the timeout ?

Run loop crash on attempted socket server close

Hi there,

Another gentleman posted about a runloop crash on an attempt to close a socket. He closed his ticket, even though there was no answer there. But I'm encountering the same issue. I've tried a bunch of stuff, but I had no luck. Any guidance would be greatly appreciated.

Thanks very much for the work on this library. I'm using it for something awesome.
Paul

VOIP Background Mode

I'd like to add support for VOIP backgrounding to enable long polling websockets for an app I've taken over support on. (Beyond the 10minute app background mode).

I know that with socketRocket I can change the NSStreamNetworkServiceType to VOIP and enable this support. Any thoughts on how to enable this in PocketSocket?

Output throttling (notification when space available to send)

A client might have a lot of messages to send, but doesn't want to push them to the WebSocket faster than they can be delivered. For example, it might want to send a while directory of files as individual messages, but if it just does it naively it'll end up reading all the files into messages and filling up memory before the socket can send them.

This can be handled by a delegate callback that tells the client that all pending messages have been sent and there's room for more. Then the client can post messages in batches. I've added this to a different WebSocket implementation and it worked well.

[Server] Compressed bit must be 0 if no negotiated deflate-frame extension

My server side code is using PSWebSocketServer (OS X 10.11.5) and sporadically I am getting this error on JavaScript client side (WKWebView, Safari 9.1.1):

[Error] WebSocket connection to 'ws://localhost:<port>' failed: Compressed bit must be 0 if no negotiated deflate-frame extension

What could it be?
Thanks!

Support IPv6 in PSWebSocketServer

Apple just announced that starting in June 2016, apps that don't support IPv6-only networks will be rejected from the App Stores. "If your app uses IPv4-specific APIs or hard-coded IP addresses, you will need to make some changes."

There is some code in PSWebSocketServer.m that constructs an IPv4 sockaddr_in from a hostname, which is then used to bind a listening socket using CFSocket.

I don't know a lot about POSIX networking APIs, so I'm not sure if this code will fail in the default case where there's no hostname given, but I'm pretty sure it will fail if a hostname is given, since it won't be able to resolve to an IPv4 address.

Capitalize the 'Connection'='upgrade' header in request

Hi guys,

I found that you use "Connection=upgrade" header when do WebSocket handshake
https://github.com/zwopple/PocketSocket/blob/master/PocketSocket/PSWebSocketDriver.m#L220

it's basically ok and conform to rfc6455

But the issue I have is that some servers expect this header as capitalized, e.g. "Connection=Upgrade"

for example, Tigase XMPP server does it this way
https://tigase.tech/projects/tigase-server/repository/revisions/master/entry/server/src/main/java/tigase/server/websocket/WebSocketXMPPIOService.java#L367

probably that's because in all rfc6455 examples it stays as capitalized, e.g.
https://tools.ietf.org/html/rfc6455#section-1.2

Are you able to do this change in this lib?
I do not see any issues with backward compatibility here

thank you

Run loop crash occurs during incomplete close.

If you open the socket without closing a previous socket the app will crash if the server goes offline. This obviously isn't a common scenario but I assume it is something that will eventually happen as it did to me.

screen shot 2014-05-09 at 12 12 30 am

To recreate this problem open a new socket more then once without ever calling close, then kill the websocket Server process it is connected to. The app will crash immediately.

How to add Subprotocol to a socket Connection

I need to add subprotocol to the following code but I don't see a way to do it. is there a way I can add sub protocol to my socket connection?

`#import <PSWebSocket/PSWebSocket.h>

@interface AppDelegate()

@Property (nonatomic, strong) PSWebSocket *socket;

@EnD
@implementation AppDelegate

  • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];

    // create the NSURLRequest that will be sent as the handshake
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"wss://example.com"]];

    // create the socket and assign delegate
    self.socket = [PSWebSocket clientSocketWithRequest:request];
    self.socket.delegate = self;

    // open socket
    [self.socket open];

    return YES;
    }
    `

Retain cycle in PSWebSocketServer?

Hello there,

First, thanks for the fantastic library.

I just found out that an NSAssert in a block somewhere in my application was causing a retain cycle. I was like, "huh?", so I checked out the definition of NSAssert, and sure enough, it references 'self':

#define NSAssert(condition, desc, ...) \
    do { \
__PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \
if (!(condition)) { \
    [[NSAssertionHandler currentHandler] handleFailureInMethod:_cmd \
object:self file:[NSString stringWithUTF8String:__FILE__] \
    lineNumber:__LINE__ description:(desc), ##__VA_ARGS__]; \
} \
        __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS \
    } while(0)
#endif

Anyway, I start searching through the application codebase, and, having included the source of PocketSocket directly in the project, I happened upon an NSAssert within a block within PSWebSocketServer around line 518. I thought you might want to know. Theoretically, it could be causing you to have to release PSWebSocketServer one too many times in order to get apparent proper dealloc behavior.

However, just a heads up, I have not confirmed that this is indeed happening or causing problems in PocketSocket.

Thanks,
Paul

Server-opened sockets always dispatch through main queue

PSWebSockets opened by PSWebSocketServer don't have any delegateQueue set. That means they call their delegate methods on the main thread. This doesn't affect the client directly, because those delegate calls get handled by the server and dispatched to its delegate on a different queue; however it means that if the main thread is busy, those delegate calls will get delayed or blocked. It would be better to avoid going through the main queue at all.

Input throttling

In writing my own WebSocket implementation earlier, I found that it needed a mechanism to pause reading from the input stream. Otherwise you can run into a situation where the remote peer is sending you messages at a high rate, but the messages are slow to be handled locally (maybe each one requires writing to disk) … the result is that memory fills up with queued-up messages. I have literally had this cause out-of-memory crashes in iOS apps.

What I did in that implementation was to add a readPaused property to the WebSocket object. I also added a boolean return value to the delegate receive-message callbacks, so they could return NO to pause the stream. (Here's the commit, if you're curious.)

PocketSocket does not link on Xcode 10.1

In a MacOS project newly created in Xcode 10.1, PocketSocket compilation throws a linker error:

Ld /Users/me/Library/Developer/Xcode/DerivedData/Whatever-arieyrqotbvrbncuwgmbqurigkkv/Build/Products/Debug/Whatever.app/Contents/MacOS/Whatever normal x86_64 (in target: Whatever)
cd /Users/me/Desktop/Whatever
export MACOSX_DEPLOYMENT_TARGET=10.13
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch x86_64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk -L/Users/me/Library/Developer/Xcode/DerivedData/Whatever-arieyrqotbvrbncuwgmbqurigkkv/Build/Products/Debug -L/Users/me/Library/Developer/Xcode/DerivedData/Whatever-arieyrqotbvrbncuwgmbqurigkkv/Build/Products/Debug/PocketSocket -F/Users/me/Library/Developer/Xcode/DerivedData/Whatever-arieyrqotbvrbncuwgmbqurigkkv/Build/Products/Debug -filelist /Users/me/Library/Developer/Xcode/DerivedData/Whatever-arieyrqotbvrbncuwgmbqurigkkv/Build/Intermediates.noindex/Whatever.build/Debug/Whatever.build/Objects-normal/x86_64/Whatever.LinkFileList -Xlinker -rpath -Xlinker @executable_path/../Frameworks -mmacosx-version-min=10.13 -Xlinker -object_path_lto -Xlinker /Users/me/Library/Developer/Xcode/DerivedData/Whatever-arieyrqotbvrbncuwgmbqurigkkv/Build/Intermediates.noindex/Whatever.build/Debug/Whatever.build/Objects-normal/x86_64/Whatever_lto.o -Xlinker -export_dynamic -Xlinker -no_deduplicate -fobjc-arc -fobjc-link-runtime -ObjC -lPocketSocket -lsystem -lz -framework CFNetwork -framework Foundation -framework Security -lPods-Whatever -Xlinker -dependency_info -Xlinker /Users/me/Library/Developer/Xcode/DerivedData/Whatever-arieyrqotbvrbncuwgmbqurigkkv/Build/Intermediates.noindex/Whatever.build/Debug/Whatever.build/Objects-normal/x86_64/Whatever_dependency_info.dat -o /Users/me/Library/Developer/Xcode/DerivedData/Whatever-arieyrqotbvrbncuwgmbqurigkkv/Build/Products/Debug/Whatever.app/Contents/MacOS/Whatever

ld: library not found for -lsystem
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Get socket client ip

How can I get address of the client connected in PSWebSocket?

I've tried

webSocket.copyStreamPropertyForKey(kCFStreamPropertySocketRemoteHostName as String)

but it returns nil.

Thank you

delegate method didCloseWithCode is not fire after close

Hello, I was checking this library if I could use in place of socketrocket or not, while testing I found issue that after closing the websocket delegate method didCloseWithCode is not firing, can anyone help me with this ?

Not working?

I've created an instance of PSWebSocketServer, set the delegate, and started, using example methods that NSLog. Now, when I try to open a websocket via javascript, it times out after 10 seconds.

TLS Support

Hi Team,

i m unable to get to the TLS.

can anyone help me to try with the TLS support, for making handshake between the web socket server and web socket client.

How it works in background ?

I use the framework to develop a IM app, but when the app enter background, it can not receive messages! What should I do?

EXC_BAD_ACCESS in PSWebSocketNetworkThread

I'm having this issue pop up when using PocketSocket, but it's not 100% reproducible. Seems to be somehow timing related. For context, I'm using the library to help unit test a web socket consumer library, so we start/stop the web socket server before/after each test. This error doesn't always happen, but seems to happen enough that it's causing us some issues.

screen shot 2014-12-17 at 10 21 03 am

Let me know if there's more information I can give you to help in tracking this down.

message ack

how can I get feedback that some message was successfully send to server? send method is dispatch to working queue asynchronously, maybe there should be also method like sendAndWait?

Server limited to ~0.5MB/s per socket

I'm using latest version as a WebSocket server on an iOS 11 application that accepts connections from an Android client using Java WebSockets.

I have noticed that data transfer is limited to about 0.5 MB/s per connection.
Any pointers as to what the problem might be?

Block implicitly retains 'self' warnings on Xcode 9

Compiling a version of the Pod from develop branch (commit
6d24e1c ) under Xcode 9.4.1 generates a bunch of warnings:

.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:61:17: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
        value = _readyState;
                ^
                self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:79:18: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
        result = _inputPaused;
                 ^
                 self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:85:28: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
        if (inputPaused != _inputPaused) {
                           ^
                           self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:86:13: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
            _inputPaused = inputPaused;
            ^
            self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:97:18: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
        result = _outputPaused;
                 ^
                 self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:103:29: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
        if (outputPaused != _outputPaused) {
                            ^
                            self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:104:13: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
            _outputPaused = outputPaused;
            ^
            self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:217:12: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
        if(_opened || _readyState != PSWebSocketReadyStateConnecting) {
           ^
           self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:217:23: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
        if(_opened || _readyState != PSWebSocketReadyStateConnecting) {
                      ^
                      self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:222:9: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
        _opened = YES;
        ^
        self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:231:13: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
        if(!_opened || _readyState == PSWebSocketReadyStateConnecting) {
            ^
            self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:231:24: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
        if(!_opened || _readyState == PSWebSocketReadyStateConnecting) {
                       ^
                       self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:237:14: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
            [_driver sendText:message];
             ^
             self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:239:14: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
            [_driver sendBinary:message];
             ^
             self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:248:14: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
            [_pingHandlers addObject:handler];
             ^
             self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:250:10: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
        [_driver sendPing:pingData];
         ^
         self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:259:12: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
        if(_readyState >= PSWebSocketReadyStateClosing) {
           ^
           self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:263:28: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
        BOOL connecting = (_readyState == PSWebSocketReadyStateConnecting);
                           ^
                           self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:264:9: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
        _readyState = PSWebSocketReadyStateClosing;
        ^
        self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:268:13: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
            _closeCode = code;
            ^
            self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:269:14: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
            [_driver sendCloseCode:code reason:reason];
             ^
             self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:296:71: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
        result = CFWriteStreamCopyProperty((__bridge CFWriteStreamRef)_outputStream, (__bridge CFStringRef)key);
                                                                      ^
                                                                      self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:302:12: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
        if(_opened || _readyState != PSWebSocketReadyStateConnecting) {
           ^
           self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:302:23: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
        if(_opened || _readyState != PSWebSocketReadyStateConnecting) {
                      ^
                      self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:306:61: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
        CFWriteStreamSetProperty((__bridge CFWriteStreamRef)_outputStream, (__bridge CFStringRef)key, (CFTypeRef)property);
                                                            ^
                                                            self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:317:38: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
            customTrustEvaluation = [_delegate respondsToSelector:@selector(webSocket:evaluateServerTrust:)];
                                     ^
                                     self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:506:13: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
            _closeCode = error.code;
            ^
            self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:507:13: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
            _closeReason = error.localizedDescription;
            ^
            self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:508:33: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
            [self closeWithCode:_closeCode reason:_closeReason];
                                ^
                                self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:508:51: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
            [self closeWithCode:_closeCode reason:_closeReason];
                                                  ^
                                                  self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:515:16: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
            if(_readyState != PSWebSocketReadyStateClosed) {
               ^
               self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:516:17: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
                _failed = YES;
                ^
                self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:517:17: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
                _readyState = PSWebSocketReadyStateClosed;
                ^
                self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:640:10: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
        [_delegate webSocketDidOpen:self];
         ^
         self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:645:10: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
        [_delegate webSocket:self didReceiveMessage:message];
         ^
         self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:650:10: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
        [_delegate webSocket:self didFailWithError:error];
         ^
         self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:655:10: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
        [_delegate webSocket:self didCloseWithCode:code reason:reason wasClean:wasClean];
         ^
         self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:660:14: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
        if ([_delegate respondsToSelector:@selector(webSocketDidFlushInput:)]) {
             ^
             self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:661:14: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
            [_delegate webSocketDidFlushInput:self];
             ^
             self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:667:14: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
        if ([_delegate respondsToSelector:@selector(webSocketDidFlushOutput:)]) {
             ^
             self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:668:14: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
            [_delegate webSocketDidFlushOutput:self];
             ^
             self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:675:14: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
        if ([_delegate respondsToSelector:@selector(webSocket:evaluateServerTrust:)]) {
             ^
             self->
.../Pods/PocketSocket/PocketSocket/PSWebSocket.m:676:23: warning: block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior [-Wimplicit-retain-self]
            result = [_delegate webSocket:self evaluateServerTrust:trust];
                      ^
                      self->
43 warnings generated.

screen shot 2018-10-31 at 14 18 53

Close method on socket client does nothing.

I am using this as my WebSocket Server -> https://github.com/einaros/ws

The PocketSocket client connects to the server but for some reason when I call
[self.socket close] or [self.socket closeWithCode:1000 reason:nil]
nothing happens.

I was previously using SocketRocket and the close method works correctly with this same server.

PocketSocket Delegate is not calling when app is in background

Hello, All.
How are you?
Currently , I am working on project using web socket server creating in iOS app.
I am feeling, PocketSocket is Best Solution for me and using this.
As of now , I am having problem in background mode.
When My App is in background, I want delegates of PocketSocket can get the event from clients and do something.
But it's not working.
Can anyone help me?
Regards.

Constant "Output stream end encountered" on server

I'm currently using PocketSocket to provide a WebSockets server. However, I'm constantly getting errors from the server socket delegate (- (void)server:server webSocket:(PSWebSocket *)webSocket didFailWithError:(NSError *)error).

Error Domain=PSWebSocketErrorDomain Code=3 "Output stream end encountered" UserInfo={NSLocalizedDescription=Output stream end encountered}

The error makes the connection to the client to stop working, but my client does not receive a close/error event, so when the client tries to send something, the socket fails (obviously). If I connect again, it works, but after a while (sometimes seconds, sometimes minutes) I get the same error.

I see from the source code that this error is related to NSStream/NSStreamEvent, but I don't know how to debug this. Can it be related to the client's WebSockets implementation?

Here's my server implementation - https://github.com/macecchi/pebble-itunesify-remote/blob/native/osx/iTunesify%20Remote/IFYPocketSocketServer.swift.

Thanks!

'Connection refused' error when trying to use a sample code

Hello,

I recently was trying to use your code to test client server WebSockets communications on iOS. I've just grabbed a client & server code from you sample and no matter which values I used, I was getting this error when was trying to connect to your WebSocket server using your WebSocket client:

The websocket handshake/connection failed with an error: Error Domain=NSPOSIXErrorDomain Code=61 "The operation couldn’t be completed. Connection refused"

Thanks!

Deadlock or crash in -[PSWebSocket dealloc]

Occasionally -[PSWebSocket dealloc] will either deadlock (iOS ≤ 9) or crash (iOS 10). The cause is the same — calling dispatch_barrier_sync(_workQueue, ...) when it's already running on the _workQueue. The behavior changes because libDispatch in iOS 10 [and presumably macOS 10.12] detects the deadlock condition and triggers a crash instead, adding to the crash report "CRASH_INFO_ENTRY_0 BUG IN CLIENT OF LIBDISPATCH: dispatch_barrier_sync called on queue already owned by current thread".

I am not sure how to fix this. The PSWebSocket is used on multiple queues/threads, so it's indeterminate which of those will make the last -release call and trigger -dealloc. If it happens to be the workQueue, the synchronous GCD dispatch to it will deadlock.

But I'm not sure removing the GCD call is not a good fix because, if -dealloc runs on a different queue, the -disconnect method would run on that queue, violating thread-safety.

On the other other hand, though, if the object is in -dealloc, that implies no other threads have references to it so there couldn't be simultaneous calls to it on other threads. Which means it should be thread-safe to operate on its ivars.

(FYI, there was an old abandoned PR #26 for doing exactly this.)

WebSocket not working anymore?

Good morning,

I updated my cocoa pod this morning and web socket don't open anymore.

You can trace it at a couple of changes. Where the asserts were replaced by NSExceptions, the logic is defective as now the return after the Exception causes it never to execute the rest of the code? Missing brackets?

Support for HTTP auth challenges

The client doesn't recognize HTTP auth challenges, i.e. a 401 response status. Instead the connection just fails (with no indication why, because the API doesn't expose what the HTTP status was.)

There would need to be new API to support this. At the very least allowing the caller to register a username and password for Basic auth, but it'd be better to have a delegate-based auth-challenge callback similar to the one NSURLConnection uses.

How to do with this error?

-[AppDelegate server:webSocket:didFailWithError:] -[AppDelegate server:webSocket:didFailWithError:] [Line 497] Socket Error: Error Domain=PSWebSocketErrorDomain Code=3 "Output stream end encountered" UserInfo={NSLocalizedDescription=Output stream end encountered}


any way to fix this bug ?

No notification if server fails to start

If the PSWebSocketServer fails to start (for example if the port is already in use), no error gets reported back to the delegate, so there's no way to know there's a problem.

Can't access websockets server on device

I run the Server test app on simulator, then I can use https://www.websocket.org/echo.html to test by connecting to ws://<127.0.0.1>:port, however, if I run the app on a device, then it's not possible to connect using ws://device-ipaddress:port. Anyone got the same issue?

P/S: I am using initWithHost:nil port:xxx to bind the server to INADDR_ANY so that supposes to use the current ip address of the device as the host.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.