├── .gitignore ├── Channel.js ├── Channels.js ├── Client.js ├── LICENSE ├── Podfile ├── Podfile.lock ├── Pods ├── Headers │ ├── Private │ │ ├── SocketRocket │ │ │ ├── NSData+SRB64Additions.h │ │ │ ├── SRWebSocket.h │ │ │ └── base64.h │ │ └── libPusher │ │ │ └── Pusher │ │ │ ├── NSDictionary+QueryString.h │ │ │ ├── NSString+Hashing.h │ │ │ ├── PTBlockEventListener.h │ │ │ ├── PTEventListener.h │ │ │ ├── PTJSON.h │ │ │ ├── PTPusher+Testing.h │ │ │ ├── PTPusher.h │ │ │ ├── PTPusherAPI.h │ │ │ ├── PTPusherChannel.h │ │ │ ├── PTPusherChannelAuthorizationOperation.h │ │ │ ├── PTPusherChannel_Private.h │ │ │ ├── PTPusherConnection.h │ │ │ ├── PTPusherDelegate.h │ │ │ ├── PTPusherErrors.h │ │ │ ├── PTPusherEvent.h │ │ │ ├── PTPusherEventDispatcher.h │ │ │ ├── PTPusherEventPublisher.h │ │ │ ├── PTPusherMacros.h │ │ │ ├── PTPusherMockConnection.h │ │ │ ├── PTPusherPresenceChannelDelegate.h │ │ │ ├── PTTargetActionEventListener.h │ │ │ ├── PTURLRequestOperation.h │ │ │ └── Pusher.h │ └── Public │ │ ├── SocketRocket │ │ ├── NSData+SRB64Additions.h │ │ ├── SRWebSocket.h │ │ └── base64.h │ │ └── libPusher │ │ └── Pusher │ │ ├── PTEventListener.h │ │ ├── PTPusher+Testing.h │ │ ├── PTPusher.h │ │ ├── PTPusherAPI.h │ │ ├── PTPusherChannel.h │ │ ├── PTPusherConnection.h │ │ ├── PTPusherDelegate.h │ │ ├── PTPusherErrors.h │ │ ├── PTPusherEvent.h │ │ ├── PTPusherEventDispatcher.h │ │ ├── PTPusherEventPublisher.h │ │ ├── PTPusherMacros.h │ │ ├── PTPusherMockConnection.h │ │ ├── PTPusherPresenceChannelDelegate.h │ │ └── Pusher.h ├── Manifest.lock ├── Pods.xcodeproj │ └── project.pbxproj ├── SocketRocket │ ├── LICENSE │ ├── README.rst │ └── SocketRocket │ │ ├── NSData+SRB64Additions.h │ │ ├── NSData+SRB64Additions.m │ │ ├── SRWebSocket.h │ │ ├── SRWebSocket.m │ │ ├── base64.c │ │ └── base64.h ├── Target Support Files │ ├── Pods-RNPusherClient-SocketRocket │ │ ├── Pods-RNPusherClient-SocketRocket-Private.xcconfig │ │ ├── Pods-RNPusherClient-SocketRocket-dummy.m │ │ ├── Pods-RNPusherClient-SocketRocket-prefix.pch │ │ └── Pods-RNPusherClient-SocketRocket.xcconfig │ ├── Pods-RNPusherClient-libPusher │ │ ├── Pods-RNPusherClient-libPusher-Private.xcconfig │ │ ├── Pods-RNPusherClient-libPusher-dummy.m │ │ ├── Pods-RNPusherClient-libPusher-prefix.pch │ │ └── Pods-RNPusherClient-libPusher.xcconfig │ └── Pods-RNPusherClient │ │ ├── Pods-RNPusherClient-acknowledgements.markdown │ │ ├── Pods-RNPusherClient-acknowledgements.plist │ │ ├── Pods-RNPusherClient-dummy.m │ │ ├── Pods-RNPusherClient-environment.h │ │ ├── Pods-RNPusherClient-resources.sh │ │ ├── Pods-RNPusherClient.debug.xcconfig │ │ └── Pods-RNPusherClient.release.xcconfig └── libPusher │ ├── LICENSE │ ├── Library │ ├── NSDictionary+QueryString.m │ ├── NSString+Hashing.m │ ├── PTBlockEventListener.m │ ├── PTEventListener.h │ ├── PTJSON.m │ ├── PTPusher+Testing.h │ ├── PTPusher+Testing.m │ ├── PTPusher.h │ ├── PTPusher.m │ ├── PTPusherAPI.h │ ├── PTPusherAPI.m │ ├── PTPusherChannel.h │ ├── PTPusherChannel.m │ ├── PTPusherChannelAuthorizationOperation.m │ ├── PTPusherConnection.h │ ├── PTPusherConnection.m │ ├── PTPusherDelegate.h │ ├── PTPusherErrors.h │ ├── PTPusherEvent.h │ ├── PTPusherEvent.m │ ├── PTPusherEventDispatcher.h │ ├── PTPusherEventDispatcher.m │ ├── PTPusherEventPublisher.h │ ├── PTPusherMacros.h │ ├── PTPusherMockConnection.h │ ├── PTPusherMockConnection.m │ ├── PTPusherPresenceChannelDelegate.h │ ├── PTTargetActionEventListener.m │ ├── PTURLRequestOperation.m │ ├── Private Headers │ │ ├── NSDictionary+QueryString.h │ │ ├── NSString+Hashing.h │ │ ├── PTBlockEventListener.h │ │ ├── PTJSON.h │ │ ├── PTPusherChannelAuthorizationOperation.h │ │ ├── PTPusherChannel_Private.h │ │ ├── PTTargetActionEventListener.h │ │ └── PTURLRequestOperation.h │ └── Pusher.h │ └── README-DIST.txt ├── README.md ├── RNPusherClient.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── RNPusherClient.xcworkspace └── contents.xcworkspacedata ├── RNPusherClient ├── RNPusherClient.h └── RNPusherClient.m ├── RNPusherClientTests └── Info.plist └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | node_modules/**/* -------------------------------------------------------------------------------- /Channel.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var React = require('react-native'); 4 | var { 5 | NativeAppEventEmitter, 6 | NativeModules: { 7 | RNPusherClient, 8 | } 9 | } = React; 10 | 11 | class Channel { 12 | constructor(name) { 13 | this.name = name; 14 | this.subscribed = false; 15 | this._callbacks = {}; 16 | 17 | this.subscription = NativeAppEventEmitter.addListener('Pusher.NewEvent', this.handleEvent.bind(this)); 18 | } 19 | 20 | handleEvent(event) { 21 | if (! this.subscribed) { 22 | return this; 23 | } 24 | 25 | // Only listen for this channel 26 | if (event.channel !== this.name) { 27 | return this; 28 | } 29 | 30 | var callbacks = this._callbacks[event.name]; 31 | if (callbacks && callbacks.length > 0) { 32 | for (var i = 0; i < callbacks.length; i++) { 33 | callbacks[i](event.data); 34 | } 35 | } 36 | 37 | return this; 38 | } 39 | 40 | subscribe() { 41 | if (this.subscribed) { 42 | return this; 43 | } 44 | 45 | RNPusherClient.subscribe(this.name); 46 | 47 | this.subscribed = true; 48 | 49 | return this; 50 | } 51 | 52 | unsubscribe() { 53 | if (!this.subscribed) { 54 | return this; 55 | } 56 | 57 | if (this.subscription && this.subscription.remove) { 58 | this.subscription.remove(); 59 | } 60 | 61 | RNPusherClient.unsubscribe(this.name); 62 | 63 | this.subscribed = false; 64 | 65 | return this; 66 | } 67 | 68 | bind(event, callback) { 69 | if (! this._callbacks.hasOwnProperty(event)) { 70 | this._callbacks[event] = []; 71 | RNPusherClient.bind(this.name, event); 72 | } 73 | 74 | this._callbacks[event].push(callback); 75 | 76 | return this; 77 | } 78 | 79 | unbind(event, callback) { 80 | if (! this._callbacks.hasOwnProperty(event)) { 81 | return this; 82 | } 83 | 84 | this._callbacks[event] = this._callbacks[event].filter((binding) => { 85 | return (binding !== callback); 86 | }); 87 | 88 | if (!this._callbacks[event].length) { 89 | delete this._callbacks[event]; 90 | } 91 | 92 | RNPusherClient.unbind(this.name, event); 93 | 94 | return this; 95 | } 96 | 97 | // trigger(event, data) { 98 | // noop (for now) 99 | // } 100 | } 101 | 102 | module.exports -------------------------------------------------------------------------------- /Channels.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Channel = require('./Channel'); 4 | 5 | class Channels { 6 | constructor() { 7 | this.channels = {}; 8 | } 9 | 10 | add(name) { 11 | if (! this.channels[name]) { 12 | this.channels[name] = new Channel(name); 13 | } 14 | return this.channels[name]; 15 | } 16 | 17 | remove(name) { 18 | if (this.channels.hasOwnProperty(name)) { 19 | var channel = this.channels[name]; 20 | delete this.channels[name]; 21 | 22 | return channel; 23 | } 24 | 25 | return false; 26 | } 27 | 28 | find(name) { 29 | return this.channels[name]; 30 | } 31 | } 32 | 33 | module.exports = Channels; 34 | -------------------------------------------------------------------------------- /Client.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var React = require('react-native'); 4 | 5 | var { 6 | NativeAppEventEmitter, 7 | NativeModules: { 8 | RNPusherClient, 9 | } 10 | } = React; 11 | 12 | var Channels = require('./Channels'); 13 | 14 | var PusherWillConnect = "Pusher.WillConnect", 15 | PusherDidConnect = "Pusher.DidConnect", 16 | PusherDidDisconnectWithError = "Pusher.DidDisconnectWithError", 17 | PusherFailedWithError = "Pusher.FailedWithError", 18 | PusherWillAutomaticallyReconnect = "Pusher.WillAutomaticallyReconnect"; 19 | 20 | var noop = () => {}; 21 | 22 | class Client { 23 | constructor(apiKey) { 24 | this.socketId = null; 25 | this.connected = false; 26 | this.channels = new Channels(); 27 | 28 | this._setupEventListeners(); 29 | 30 | RNPusherClient.connect(apiKey); 31 | } 32 | 33 | subscribe(name) { 34 | var channel = this.channels.add(name); 35 | channel.subscribe(); 36 | 37 | return channel; 38 | } 39 | 40 | unsubscribe(name) { 41 | this.channels.remove(name); 42 | 43 | return this; 44 | } 45 | 46 | channel(name) { 47 | var channel = this.rooms.channel(name); 48 | if (!channel) { 49 | channel = this.subscribe(name); 50 | } 51 | 52 | return channel; 53 | } 54 | 55 | onWillConnect() { 56 | // noop 57 | } 58 | 59 | onDidConnect(socketId) { 60 | this.socketId = socketId; 61 | this.connected = true; 62 | } 63 | 64 | onDidDisconnectWithError(error) { 65 | this.socketId = null; 66 | this.connected = false; 67 | } 68 | 69 | onFailedWithError(error) { 70 | this.connected = false; 71 | } 72 | 73 | _setupEventListeners() { 74 | NativeAppEventEmitter.addListener(PusherWillConnect, this.onWillConnect.bind(this)); 75 | NativeAppEventEmitter.addListener(PusherDidConnect, this.onDidConnect.bind(this)); 76 | NativeAppEventEmitter.addListener(PusherDidDisconnectWithError, this.onDidDisconnectWithError.bind(this)); 77 | NativeAppEventEmitter.addListener(PusherFailedWithError, this.onFailedWithError.bind(this)); 78 | } 79 | 80 | } 81 | 82 | 83 | module.exports = Client; 84 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Tackk Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '6.0' 3 | 4 | target 'RNPusherClient' do 5 | pod 'libPusher', '~> 1.6' 6 | end 7 | 8 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - libPusher (1.6): 3 | - libPusher/Core (= 1.6) 4 | - libPusher/Core (1.6): 5 | - SocketRocket (= 0.3.1-beta2) 6 | - SocketRocket (0.3.1-beta2) 7 | 8 | DEPENDENCIES: 9 | - libPusher (~> 1.6) 10 | 11 | SPEC CHECKSUMS: 12 | libPusher: f9367ede8f5141e74adc90ba20536cbc3c7b68e1 13 | SocketRocket: 7284ab9370a06c99aba92b2fe3a32aedd0f9a6fa 14 | 15 | COCOAPODS: 0.37.2 16 | -------------------------------------------------------------------------------- /Pods/Headers/Private/SocketRocket/NSData+SRB64Additions.h: -------------------------------------------------------------------------------- 1 | ../../../SocketRocket/SocketRocket/NSData+SRB64Additions.h -------------------------------------------------------------------------------- /Pods/Headers/Private/SocketRocket/SRWebSocket.h: -------------------------------------------------------------------------------- 1 | ../../../SocketRocket/SocketRocket/SRWebSocket.h -------------------------------------------------------------------------------- /Pods/Headers/Private/SocketRocket/base64.h: -------------------------------------------------------------------------------- 1 | ../../../SocketRocket/SocketRocket/base64.h -------------------------------------------------------------------------------- /Pods/Headers/Private/libPusher/Pusher/NSDictionary+QueryString.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/Private Headers/NSDictionary+QueryString.h -------------------------------------------------------------------------------- /Pods/Headers/Private/libPusher/Pusher/NSString+Hashing.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/Private Headers/NSString+Hashing.h -------------------------------------------------------------------------------- /Pods/Headers/Private/libPusher/Pusher/PTBlockEventListener.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/Private Headers/PTBlockEventListener.h -------------------------------------------------------------------------------- /Pods/Headers/Private/libPusher/Pusher/PTEventListener.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTEventListener.h -------------------------------------------------------------------------------- /Pods/Headers/Private/libPusher/Pusher/PTJSON.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/Private Headers/PTJSON.h -------------------------------------------------------------------------------- /Pods/Headers/Private/libPusher/Pusher/PTPusher+Testing.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTPusher+Testing.h -------------------------------------------------------------------------------- /Pods/Headers/Private/libPusher/Pusher/PTPusher.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTPusher.h -------------------------------------------------------------------------------- /Pods/Headers/Private/libPusher/Pusher/PTPusherAPI.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTPusherAPI.h -------------------------------------------------------------------------------- /Pods/Headers/Private/libPusher/Pusher/PTPusherChannel.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTPusherChannel.h -------------------------------------------------------------------------------- /Pods/Headers/Private/libPusher/Pusher/PTPusherChannelAuthorizationOperation.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/Private Headers/PTPusherChannelAuthorizationOperation.h -------------------------------------------------------------------------------- /Pods/Headers/Private/libPusher/Pusher/PTPusherChannel_Private.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/Private Headers/PTPusherChannel_Private.h -------------------------------------------------------------------------------- /Pods/Headers/Private/libPusher/Pusher/PTPusherConnection.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTPusherConnection.h -------------------------------------------------------------------------------- /Pods/Headers/Private/libPusher/Pusher/PTPusherDelegate.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTPusherDelegate.h -------------------------------------------------------------------------------- /Pods/Headers/Private/libPusher/Pusher/PTPusherErrors.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTPusherErrors.h -------------------------------------------------------------------------------- /Pods/Headers/Private/libPusher/Pusher/PTPusherEvent.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTPusherEvent.h -------------------------------------------------------------------------------- /Pods/Headers/Private/libPusher/Pusher/PTPusherEventDispatcher.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTPusherEventDispatcher.h -------------------------------------------------------------------------------- /Pods/Headers/Private/libPusher/Pusher/PTPusherEventPublisher.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTPusherEventPublisher.h -------------------------------------------------------------------------------- /Pods/Headers/Private/libPusher/Pusher/PTPusherMacros.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTPusherMacros.h -------------------------------------------------------------------------------- /Pods/Headers/Private/libPusher/Pusher/PTPusherMockConnection.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTPusherMockConnection.h -------------------------------------------------------------------------------- /Pods/Headers/Private/libPusher/Pusher/PTPusherPresenceChannelDelegate.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTPusherPresenceChannelDelegate.h -------------------------------------------------------------------------------- /Pods/Headers/Private/libPusher/Pusher/PTTargetActionEventListener.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/Private Headers/PTTargetActionEventListener.h -------------------------------------------------------------------------------- /Pods/Headers/Private/libPusher/Pusher/PTURLRequestOperation.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/Private Headers/PTURLRequestOperation.h -------------------------------------------------------------------------------- /Pods/Headers/Private/libPusher/Pusher/Pusher.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/Pusher.h -------------------------------------------------------------------------------- /Pods/Headers/Public/SocketRocket/NSData+SRB64Additions.h: -------------------------------------------------------------------------------- 1 | ../../../SocketRocket/SocketRocket/NSData+SRB64Additions.h -------------------------------------------------------------------------------- /Pods/Headers/Public/SocketRocket/SRWebSocket.h: -------------------------------------------------------------------------------- 1 | ../../../SocketRocket/SocketRocket/SRWebSocket.h -------------------------------------------------------------------------------- /Pods/Headers/Public/SocketRocket/base64.h: -------------------------------------------------------------------------------- 1 | ../../../SocketRocket/SocketRocket/base64.h -------------------------------------------------------------------------------- /Pods/Headers/Public/libPusher/Pusher/PTEventListener.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTEventListener.h -------------------------------------------------------------------------------- /Pods/Headers/Public/libPusher/Pusher/PTPusher+Testing.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTPusher+Testing.h -------------------------------------------------------------------------------- /Pods/Headers/Public/libPusher/Pusher/PTPusher.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTPusher.h -------------------------------------------------------------------------------- /Pods/Headers/Public/libPusher/Pusher/PTPusherAPI.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTPusherAPI.h -------------------------------------------------------------------------------- /Pods/Headers/Public/libPusher/Pusher/PTPusherChannel.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTPusherChannel.h -------------------------------------------------------------------------------- /Pods/Headers/Public/libPusher/Pusher/PTPusherConnection.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTPusherConnection.h -------------------------------------------------------------------------------- /Pods/Headers/Public/libPusher/Pusher/PTPusherDelegate.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTPusherDelegate.h -------------------------------------------------------------------------------- /Pods/Headers/Public/libPusher/Pusher/PTPusherErrors.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTPusherErrors.h -------------------------------------------------------------------------------- /Pods/Headers/Public/libPusher/Pusher/PTPusherEvent.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTPusherEvent.h -------------------------------------------------------------------------------- /Pods/Headers/Public/libPusher/Pusher/PTPusherEventDispatcher.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTPusherEventDispatcher.h -------------------------------------------------------------------------------- /Pods/Headers/Public/libPusher/Pusher/PTPusherEventPublisher.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTPusherEventPublisher.h -------------------------------------------------------------------------------- /Pods/Headers/Public/libPusher/Pusher/PTPusherMacros.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTPusherMacros.h -------------------------------------------------------------------------------- /Pods/Headers/Public/libPusher/Pusher/PTPusherMockConnection.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTPusherMockConnection.h -------------------------------------------------------------------------------- /Pods/Headers/Public/libPusher/Pusher/PTPusherPresenceChannelDelegate.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/PTPusherPresenceChannelDelegate.h -------------------------------------------------------------------------------- /Pods/Headers/Public/libPusher/Pusher/Pusher.h: -------------------------------------------------------------------------------- 1 | ../../../../libPusher/Library/Pusher.h -------------------------------------------------------------------------------- /Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - libPusher (1.6): 3 | - libPusher/Core (= 1.6) 4 | - libPusher/Core (1.6): 5 | - SocketRocket (= 0.3.1-beta2) 6 | - SocketRocket (0.3.1-beta2) 7 | 8 | DEPENDENCIES: 9 | - libPusher (~> 1.6) 10 | 11 | SPEC CHECKSUMS: 12 | libPusher: f9367ede8f5141e74adc90ba20536cbc3c7b68e1 13 | SocketRocket: 7284ab9370a06c99aba92b2fe3a32aedd0f9a6fa 14 | 15 | COCOAPODS: 0.37.2 16 | -------------------------------------------------------------------------------- /Pods/SocketRocket/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Copyright 2012 Square Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | -------------------------------------------------------------------------------- /Pods/SocketRocket/README.rst: -------------------------------------------------------------------------------- 1 | SocketRocket Objective-C WebSocket Client (beta) 2 | ================================================ 3 | A conforming WebSocket (`RFC 6455 `_) 4 | client library. 5 | 6 | `Test results for SocketRocket here `_. 7 | You can compare to what `modern browsers look like here 8 | `_. 9 | 10 | SocketRocket currently conforms to all ~300 of `Autobahn 11 | `_'s fuzzing tests (aside from 12 | two UTF-8 ones where it is merely *non-strict*. tests 6.4.2 and 6.4.4) 13 | 14 | Features/Design 15 | --------------- 16 | - TLS (wss) support. It uses CFStream so we get this for *free* 17 | - Uses NSStream/CFNetworking. Earlier implementations used ``dispatch_io``, 18 | however, this proved to be make TLS nearly impossible. Also I wanted this to 19 | work in iOS 4.x. (SocketRocket only supports 5.0 and above now) 20 | - Uses ARC. It uses the 4.0 compatible subset (no weak refs). 21 | - Seems to perform quite well 22 | - Parallel architecture. Most of the work is done in background worker queues. 23 | - Delegate-based. Had older versions that could use blocks too, but I felt it 24 | didn't blend well with retain cycles and just objective C in general. 25 | 26 | Changes 27 | ------- 28 | 29 | v0.3.1-beta2 - 2013-01-12 30 | ````````````````````````` 31 | 32 | - Stability fix for ``closeWithCode:reason:`` (Thanks @michaelpetrov!) 33 | - Actually clean up the NSStreams and remove them from their runloops 34 | - ``_SRRunLoopThread``'s ``main`` wasn't correctly wrapped with 35 | ``@autoreleasepool`` 36 | 37 | v0.3.1-beta1 - 2013-01-12 38 | ````````````````````````` 39 | 40 | - Cleaned up GCD so OS_OBJECT_USE_OBJC_RETAIN_RELEASE is optional 41 | - Removed deprecated ``dispatch_get_current_queue`` in favor of ``dispatch_queue_set_specific`` and ``dispatch_get_specific`` 42 | - Dropping support for iOS 4.0 (it may still work) 43 | 44 | 45 | Installing (iOS) 46 | ---------------- 47 | There's a few options. Choose one, or just figure it out 48 | 49 | - You can copy all the files in the SocketRocket group into your app. 50 | - Include SocketRocket as a subproject and use libSocketRocket 51 | 52 | If you do this, you must add -ObjC to your "other linker flags" option 53 | 54 | - For OS X you will have to repackage make a .framework target. I will take 55 | contributions. Message me if you are interested. 56 | 57 | 58 | Depending on how you configure your project you may need to ``#import`` either 59 | ```` or ``"SRSocketRocket.h"`` 60 | 61 | Framework Dependencies 62 | `````````````````````` 63 | Your .app must be linked against the following frameworks/dylibs 64 | 65 | - libicucore.dylib 66 | - CFNetwork.framework 67 | - Security.framework 68 | - Foundation.framework 69 | 70 | Installing (OS X) 71 | ----------------- 72 | SocketRocket now has (64-bit only) OS X support. ``SocketRocket.framework`` 73 | inside Xcode project is for OS X only. It should be identical in function aside 74 | from the unicode validation. ICU isn't shipped with OS X which is what the 75 | original implementation used for unicode validation. The workaround is much 76 | more rhudimentary and less robust. 77 | 78 | 1. Add SocketRocket.xcodeproj as either a subproject of your app or in your workspace. 79 | 2. Add ``SocketRocket.framework`` to the link libraries 80 | 3. If you don't have a "copy files" step for ``Framework``, create one 81 | 4. Add ``SocketRocket.framework`` to the "copy files" step. 82 | 83 | API 84 | --- 85 | The classes 86 | 87 | ``SRWebSocket`` 88 | ``````````````` 89 | The Web Socket. 90 | 91 | .. note:: ``SRWebSocket`` will retain itself between ``-(void)open`` and when it 92 | closes, errors, or fails. This is similar to how ``NSURLConnection`` behaves. 93 | (unlike ``NSURLConnection``, ``SRWebSocket`` won't retain the delegate) 94 | 95 | What you need to know 96 | 97 | .. code-block:: objective-c 98 | 99 | @interface SRWebSocket : NSObject 100 | 101 | // Make it with this 102 | - (id)initWithURLRequest:(NSURLRequest *)request; 103 | 104 | // Set this before opening 105 | @property (nonatomic, assign) id delegate; 106 | 107 | - (void)open; 108 | 109 | // Close it with this 110 | - (void)close; 111 | 112 | // Send a UTF8 String or Data 113 | - (void)send:(id)data; 114 | 115 | @end 116 | 117 | ``SRWebSocketDelegate`` 118 | ``````````````````````` 119 | You implement this 120 | 121 | .. code-block:: objective-c 122 | 123 | @protocol SRWebSocketDelegate 124 | 125 | - (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message; 126 | 127 | @optional 128 | 129 | - (void)webSocketDidOpen:(SRWebSocket *)webSocket; 130 | - (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error; 131 | - (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean; 132 | 133 | @end 134 | 135 | Known Issues/Server Todo's 136 | -------------------------- 137 | - Needs auth delegates (like in NSURLConnection) 138 | - Move the streams off the main runloop (most of the work is backgrounded uses 139 | GCD, but I just haven't gotten around to moving it off the main loop since I 140 | converted it from dispatch_io) 141 | - Re-implement server. I removed an existing implementation as well because it 142 | wasn't being used and I wasn't super happy with the interface. Will revisit 143 | this. 144 | - Separate framer and client logic. This will make it nicer when having a 145 | server. 146 | 147 | Testing 148 | ------- 149 | Included are setup scripts for the python testing environment. It comes 150 | packaged with vitualenv so all the dependencies are installed in userland. 151 | 152 | To run the short test from the command line, run:: 153 | 154 | make test 155 | 156 | To run all the tests, run:: 157 | 158 | make test_all 159 | 160 | The short tests don't include the performance tests. (the test harness is 161 | actually the bottleneck, not SocketRocket). 162 | 163 | The first time this is run, it may take a while to install the dependencies. It 164 | will be smooth sailing after that. After the test runs the makefile will open 165 | the results page in your browser. If nothing comes up, you failed. Working on 166 | making this interface a bit nicer. 167 | 168 | To run from the app, choose the ``SocketRocket`` target and run the test action 169 | (``cmd+u``). It runs the same thing, but makes it easier to debug. There is 170 | some serious pre/post hooks in the Test action. You can edit it to customize 171 | behavior. 172 | 173 | .. note:: Xcode only up to version 4.4 is currently supported for the test 174 | harness 175 | 176 | TestChat Demo Application 177 | ------------------------- 178 | SocketRocket includes a demo app, TestChat. It will "chat" with a listening 179 | websocket on port 9900. 180 | 181 | It's a simple project. Uses storyboard. Storyboard is sweet. 182 | 183 | 184 | TestChat Server 185 | ``````````````` 186 | We've included a small server for the chat app. It has a simple function. 187 | It will take a message and broadcast it to all other connected clients. 188 | 189 | We have to get some dependencies. We also want to reuse the virtualenv we made 190 | when we ran the tests. If you haven't run the tests yet, go into the 191 | SocketRocket root directory and type:: 192 | 193 | make test 194 | 195 | This will set up your `virtualenv `_. 196 | Now, in your terminal:: 197 | 198 | source .env/bin/activate 199 | pip install git+https://github.com/facebook/tornado.git 200 | 201 | In the same terminal session, start the chatroom server:: 202 | 203 | python TestChatServer/py/chatroom.py 204 | 205 | There's also a Go implementation (with the latest weekly) where you can:: 206 | 207 | cd TestChatServer/go 208 | go run chatroom.go 209 | 210 | Chatting 211 | ```````` 212 | Now, start TestChat.app (just run the target in the XCode project). If you had 213 | it started already you can hit the refresh button to reconnect. It should say 214 | "Connected!" on top. 215 | 216 | To talk with the app, open up your browser to `http://localhost:9000 `_ and 217 | start chatting. 218 | 219 | 220 | WebSocket Server Implementation Recommendations 221 | ----------------------------------------------- 222 | SocketRocket has been used with the following libraries: 223 | 224 | - `Tornado `_ 225 | - Go's `weekly build `_ (the official release has an 226 | outdated protocol, so you may have to use weekly until `Go 1 227 | `_ is released) 228 | - `Autobahn `_ (using its fuzzing 229 | client) 230 | 231 | The Tornado one is dirt simple and works like a charm. (`IPython notebook 232 | `_ uses it 233 | too). It's much easier to configure handlers and routes than in 234 | Autobahn/twisted. 235 | 236 | As far as Go's goes, it works in my limited testing. I much prefer go's 237 | concurrency model as well. Try it! You may like it. 238 | It could use some more control over things such as pings, etc., but I 239 | am sure it will come in time. 240 | 241 | Autobahn is a great test suite. The Python server code is good, and conforms 242 | well (obviously). Hovever, for me, twisted would be a deal-breaker for writing 243 | something new. I find it a bit too complex and heavy for a simple service. If 244 | you are already using twisted though, Autobahn is probably for you. 245 | 246 | Contributing 247 | ------------ 248 | Any contributors to the master SocketRocket repository must sign the `Individual 249 | Contributor License Agreement 250 | (CLA) 251 | `_. 252 | It's a short form that covers our bases and makes sure you're eligible to 253 | contribute. 254 | 255 | When you have a change you'd like to see in the master repository, `send a pull 256 | request `_. Before we merge your 257 | request, we'll make sure you're in the list of people who have signed a CLA. 258 | -------------------------------------------------------------------------------- /Pods/SocketRocket/SocketRocket/NSData+SRB64Additions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2012 Square Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | 19 | 20 | @interface NSData (SRB64Additions) 21 | 22 | - (NSString *)SR_stringByBase64Encoding; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Pods/SocketRocket/SocketRocket/NSData+SRB64Additions.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2012 Square Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import "NSData+SRB64Additions.h" 18 | #import "base64.h" 19 | 20 | 21 | @implementation NSData (SRB64Additions) 22 | 23 | - (NSString *)SR_stringByBase64Encoding; 24 | { 25 | size_t buffer_size = (([self length] * 3 + 2) / 2); 26 | 27 | char *buffer = (char *)malloc(buffer_size); 28 | 29 | int len = b64_ntop([self bytes], [self length], buffer, buffer_size); 30 | 31 | if (len == -1) { 32 | free(buffer); 33 | return nil; 34 | } else{ 35 | return [[NSString alloc] initWithBytesNoCopy:buffer length:len encoding:NSUTF8StringEncoding freeWhenDone:YES]; 36 | } 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /Pods/SocketRocket/SocketRocket/SRWebSocket.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2012 Square Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import 18 | #import 19 | 20 | typedef enum { 21 | SR_CONNECTING = 0, 22 | SR_OPEN = 1, 23 | SR_CLOSING = 2, 24 | SR_CLOSED = 3, 25 | } SRReadyState; 26 | 27 | @class SRWebSocket; 28 | 29 | extern NSString *const SRWebSocketErrorDomain; 30 | 31 | #pragma mark - SRWebSocketDelegate 32 | 33 | @protocol SRWebSocketDelegate; 34 | 35 | #pragma mark - SRWebSocket 36 | 37 | @interface SRWebSocket : NSObject 38 | 39 | @property (nonatomic, assign) id delegate; 40 | 41 | @property (nonatomic, readonly) SRReadyState readyState; 42 | @property (nonatomic, readonly, retain) NSURL *url; 43 | 44 | // This returns the negotiated protocol. 45 | // It will be nil until after the handshake completes. 46 | @property (nonatomic, readonly, copy) NSString *protocol; 47 | 48 | // Protocols should be an array of strings that turn into Sec-WebSocket-Protocol. 49 | - (id)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols; 50 | - (id)initWithURLRequest:(NSURLRequest *)request; 51 | 52 | // Some helper constructors. 53 | - (id)initWithURL:(NSURL *)url protocols:(NSArray *)protocols; 54 | - (id)initWithURL:(NSURL *)url; 55 | 56 | // Delegate queue will be dispatch_main_queue by default. 57 | // You cannot set both OperationQueue and dispatch_queue. 58 | - (void)setDelegateOperationQueue:(NSOperationQueue*) queue; 59 | - (void)setDelegateDispatchQueue:(dispatch_queue_t) queue; 60 | 61 | // By default, it will schedule itself on +[NSRunLoop SR_networkRunLoop] using defaultModes. 62 | - (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode; 63 | - (void)unscheduleFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode; 64 | 65 | // SRWebSockets are intended for one-time-use only. Open should be called once and only once. 66 | - (void)open; 67 | 68 | - (void)close; 69 | - (void)closeWithCode:(NSInteger)code reason:(NSString *)reason; 70 | 71 | // Send a UTF8 String or Data. 72 | - (void)send:(id)data; 73 | 74 | @end 75 | 76 | #pragma mark - SRWebSocketDelegate 77 | 78 | @protocol SRWebSocketDelegate 79 | 80 | // message will either be an NSString if the server is using text 81 | // or NSData if the server is using binary. 82 | - (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message; 83 | 84 | @optional 85 | 86 | - (void)webSocketDidOpen:(SRWebSocket *)webSocket; 87 | - (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error; 88 | - (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean; 89 | 90 | @end 91 | 92 | #pragma mark - NSURLRequest (CertificateAdditions) 93 | 94 | @interface NSURLRequest (CertificateAdditions) 95 | 96 | @property (nonatomic, retain, readonly) NSArray *SR_SSLPinnedCertificates; 97 | 98 | @end 99 | 100 | #pragma mark - NSMutableURLRequest (CertificateAdditions) 101 | 102 | @interface NSMutableURLRequest (CertificateAdditions) 103 | 104 | @property (nonatomic, retain) NSArray *SR_SSLPinnedCertificates; 105 | 106 | @end 107 | 108 | #pragma mark - NSRunLoop (SRWebSocket) 109 | 110 | @interface NSRunLoop (SRWebSocket) 111 | 112 | + (NSRunLoop *)SR_networkRunLoop; 113 | 114 | @end 115 | -------------------------------------------------------------------------------- /Pods/SocketRocket/SocketRocket/base64.c: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: base64.c,v 1.5 2006/10/21 09:55:03 otto Exp $ */ 2 | 3 | /* 4 | * Copyright (c) 1996 by Internet Software Consortium. 5 | * 6 | * Permission to use, copy, modify, and distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 11 | * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 12 | * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 13 | * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 | * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 | * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 16 | * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 17 | * SOFTWARE. 18 | */ 19 | 20 | /* 21 | * Portions Copyright (c) 1995 by International Business Machines, Inc. 22 | * 23 | * International Business Machines, Inc. (hereinafter called IBM) grants 24 | * permission under its copyrights to use, copy, modify, and distribute this 25 | * Software with or without fee, provided that the above copyright notice and 26 | * all paragraphs of this notice appear in all copies, and that the name of IBM 27 | * not be used in connection with the marketing of any product incorporating 28 | * the Software or modifications thereof, without specific, written prior 29 | * permission. 30 | * 31 | * To the extent it has a right to do so, IBM grants an immunity from suit 32 | * under its patents, if any, for the use, sale or manufacture of products to 33 | * the extent that such products are used for performing Domain Name System 34 | * dynamic updates in TCP/IP networks by means of the Software. No immunity is 35 | * granted for any product per se or for any other function of any product. 36 | * 37 | * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, 38 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 39 | * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, 40 | * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING 41 | * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN 42 | * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. 43 | */ 44 | 45 | /* OPENBSD ORIGINAL: lib/libc/net/base64.c */ 46 | 47 | 48 | #if (!defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP)) || (!defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON)) 49 | 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | 56 | #include 57 | #include 58 | 59 | #include 60 | #include 61 | 62 | #include "base64.h" 63 | 64 | static const char Base64[] = 65 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 66 | static const char Pad64 = '='; 67 | 68 | /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) 69 | The following encoding technique is taken from RFC 1521 by Borenstein 70 | and Freed. It is reproduced here in a slightly edited form for 71 | convenience. 72 | 73 | A 65-character subset of US-ASCII is used, enabling 6 bits to be 74 | represented per printable character. (The extra 65th character, "=", 75 | is used to signify a special processing function.) 76 | 77 | The encoding process represents 24-bit groups of input bits as output 78 | strings of 4 encoded characters. Proceeding from left to right, a 79 | 24-bit input group is formed by concatenating 3 8-bit input groups. 80 | These 24 bits are then treated as 4 concatenated 6-bit groups, each 81 | of which is translated into a single digit in the base64 alphabet. 82 | 83 | Each 6-bit group is used as an index into an array of 64 printable 84 | characters. The character referenced by the index is placed in the 85 | output string. 86 | 87 | Table 1: The Base64 Alphabet 88 | 89 | Value Encoding Value Encoding Value Encoding Value Encoding 90 | 0 A 17 R 34 i 51 z 91 | 1 B 18 S 35 j 52 0 92 | 2 C 19 T 36 k 53 1 93 | 3 D 20 U 37 l 54 2 94 | 4 E 21 V 38 m 55 3 95 | 5 F 22 W 39 n 56 4 96 | 6 G 23 X 40 o 57 5 97 | 7 H 24 Y 41 p 58 6 98 | 8 I 25 Z 42 q 59 7 99 | 9 J 26 a 43 r 60 8 100 | 10 K 27 b 44 s 61 9 101 | 11 L 28 c 45 t 62 + 102 | 12 M 29 d 46 u 63 / 103 | 13 N 30 e 47 v 104 | 14 O 31 f 48 w (pad) = 105 | 15 P 32 g 49 x 106 | 16 Q 33 h 50 y 107 | 108 | Special processing is performed if fewer than 24 bits are available 109 | at the end of the data being encoded. A full encoding quantum is 110 | always completed at the end of a quantity. When fewer than 24 input 111 | bits are available in an input group, zero bits are added (on the 112 | right) to form an integral number of 6-bit groups. Padding at the 113 | end of the data is performed using the '=' character. 114 | 115 | Since all base64 input is an integral number of octets, only the 116 | ------------------------------------------------- 117 | following cases can arise: 118 | 119 | (1) the final quantum of encoding input is an integral 120 | multiple of 24 bits; here, the final unit of encoded 121 | output will be an integral multiple of 4 characters 122 | with no "=" padding, 123 | (2) the final quantum of encoding input is exactly 8 bits; 124 | here, the final unit of encoded output will be two 125 | characters followed by two "=" padding characters, or 126 | (3) the final quantum of encoding input is exactly 16 bits; 127 | here, the final unit of encoded output will be three 128 | characters followed by one "=" padding character. 129 | */ 130 | 131 | #if !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) 132 | int 133 | b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) 134 | { 135 | size_t datalength = 0; 136 | u_char input[3]; 137 | u_char output[4]; 138 | u_int i; 139 | 140 | while (2 < srclength) { 141 | input[0] = *src++; 142 | input[1] = *src++; 143 | input[2] = *src++; 144 | srclength -= 3; 145 | 146 | output[0] = input[0] >> 2; 147 | output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); 148 | output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); 149 | output[3] = input[2] & 0x3f; 150 | 151 | if (datalength + 4 > targsize) 152 | return (-1); 153 | target[datalength++] = Base64[output[0]]; 154 | target[datalength++] = Base64[output[1]]; 155 | target[datalength++] = Base64[output[2]]; 156 | target[datalength++] = Base64[output[3]]; 157 | } 158 | 159 | /* Now we worry about padding. */ 160 | if (0 != srclength) { 161 | /* Get what's left. */ 162 | input[0] = input[1] = input[2] = '\0'; 163 | for (i = 0; i < srclength; i++) 164 | input[i] = *src++; 165 | 166 | output[0] = input[0] >> 2; 167 | output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); 168 | output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); 169 | 170 | if (datalength + 4 > targsize) 171 | return (-1); 172 | target[datalength++] = Base64[output[0]]; 173 | target[datalength++] = Base64[output[1]]; 174 | if (srclength == 1) 175 | target[datalength++] = Pad64; 176 | else 177 | target[datalength++] = Base64[output[2]]; 178 | target[datalength++] = Pad64; 179 | } 180 | if (datalength >= targsize) 181 | return (-1); 182 | target[datalength] = '\0'; /* Returned value doesn't count \0. */ 183 | return (datalength); 184 | } 185 | #endif /* !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) */ 186 | 187 | #if !defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON) 188 | 189 | /* skips all whitespace anywhere. 190 | converts characters, four at a time, starting at (or after) 191 | src from base - 64 numbers into three 8 bit bytes in the target area. 192 | it returns the number of data bytes stored at the target, or -1 on error. 193 | */ 194 | 195 | int 196 | b64_pton(char const *src, u_char *target, size_t targsize) 197 | { 198 | u_int tarindex, state; 199 | int ch; 200 | char *pos; 201 | 202 | state = 0; 203 | tarindex = 0; 204 | 205 | while ((ch = *src++) != '\0') { 206 | if (isspace(ch)) /* Skip whitespace anywhere. */ 207 | continue; 208 | 209 | if (ch == Pad64) 210 | break; 211 | 212 | pos = strchr(Base64, ch); 213 | if (pos == 0) /* A non-base64 character. */ 214 | return (-1); 215 | 216 | switch (state) { 217 | case 0: 218 | if (target) { 219 | if (tarindex >= targsize) 220 | return (-1); 221 | target[tarindex] = (pos - Base64) << 2; 222 | } 223 | state = 1; 224 | break; 225 | case 1: 226 | if (target) { 227 | if (tarindex + 1 >= targsize) 228 | return (-1); 229 | target[tarindex] |= (pos - Base64) >> 4; 230 | target[tarindex+1] = ((pos - Base64) & 0x0f) 231 | << 4 ; 232 | } 233 | tarindex++; 234 | state = 2; 235 | break; 236 | case 2: 237 | if (target) { 238 | if (tarindex + 1 >= targsize) 239 | return (-1); 240 | target[tarindex] |= (pos - Base64) >> 2; 241 | target[tarindex+1] = ((pos - Base64) & 0x03) 242 | << 6; 243 | } 244 | tarindex++; 245 | state = 3; 246 | break; 247 | case 3: 248 | if (target) { 249 | if (tarindex >= targsize) 250 | return (-1); 251 | target[tarindex] |= (pos - Base64); 252 | } 253 | tarindex++; 254 | state = 0; 255 | break; 256 | } 257 | } 258 | 259 | /* 260 | * We are done decoding Base-64 chars. Let's see if we ended 261 | * on a byte boundary, and/or with erroneous trailing characters. 262 | */ 263 | 264 | if (ch == Pad64) { /* We got a pad char. */ 265 | ch = *src++; /* Skip it, get next. */ 266 | switch (state) { 267 | case 0: /* Invalid = in first position */ 268 | case 1: /* Invalid = in second position */ 269 | return (-1); 270 | 271 | case 2: /* Valid, means one byte of info */ 272 | /* Skip any number of spaces. */ 273 | for (; ch != '\0'; ch = *src++) 274 | if (!isspace(ch)) 275 | break; 276 | /* Make sure there is another trailing = sign. */ 277 | if (ch != Pad64) 278 | return (-1); 279 | ch = *src++; /* Skip the = */ 280 | /* Fall through to "single trailing =" case. */ 281 | /* FALLTHROUGH */ 282 | 283 | case 3: /* Valid, means two bytes of info */ 284 | /* 285 | * We know this char is an =. Is there anything but 286 | * whitespace after it? 287 | */ 288 | for (; ch != '\0'; ch = *src++) 289 | if (!isspace(ch)) 290 | return (-1); 291 | 292 | /* 293 | * Now make sure for cases 2 and 3 that the "extra" 294 | * bits that slopped past the last full byte were 295 | * zeros. If we don't check them, they become a 296 | * subliminal channel. 297 | */ 298 | if (target && target[tarindex] != 0) 299 | return (-1); 300 | } 301 | } else { 302 | /* 303 | * We ended by seeing the end of the string. Make sure we 304 | * have no partial bytes lying around. 305 | */ 306 | if (state != 0) 307 | return (-1); 308 | } 309 | 310 | return (tarindex); 311 | } 312 | 313 | #endif /* !defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON) */ 314 | #endif 315 | -------------------------------------------------------------------------------- /Pods/SocketRocket/SocketRocket/base64.h: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Square Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | 16 | 17 | #ifndef SocketRocket_base64_h 18 | #define SocketRocket_base64_h 19 | 20 | #include 21 | 22 | extern int 23 | b64_ntop(u_char const *src, 24 | size_t srclength, 25 | char *target, 26 | size_t targsize); 27 | 28 | extern int 29 | b64_pton(char const *src, 30 | u_char *target, 31 | size_t targsize); 32 | 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-RNPusherClient-SocketRocket/Pods-RNPusherClient-SocketRocket-Private.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods-RNPusherClient-SocketRocket.xcconfig" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/SocketRocket" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/SocketRocket" "${PODS_ROOT}/Headers/Public/libPusher" "${PODS_ROOT}/Headers/Public/libPusher/Pusher" 4 | OTHER_LDFLAGS = ${PODS_RNPUSHERCLIENT_SOCKETROCKET_OTHER_LDFLAGS} -ObjC 5 | PODS_ROOT = ${SRCROOT} 6 | SKIP_INSTALL = YES -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-RNPusherClient-SocketRocket/Pods-RNPusherClient-SocketRocket-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_RNPusherClient_SocketRocket : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_RNPusherClient_SocketRocket 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-RNPusherClient-SocketRocket/Pods-RNPusherClient-SocketRocket-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | #import "Pods-RNPusherClient-environment.h" 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-RNPusherClient-SocketRocket/Pods-RNPusherClient-SocketRocket.xcconfig: -------------------------------------------------------------------------------- 1 | PODS_RNPUSHERCLIENT_SOCKETROCKET_OTHER_LDFLAGS = -l"icucore" -framework "CFNetwork" -framework "Security" -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-RNPusherClient-libPusher/Pods-RNPusherClient-libPusher-Private.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods-RNPusherClient-libPusher.xcconfig" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 ${PODS_RNPUSHERCLIENT_LIBPUSHER_GCC_PREPROCESSOR_DEFINITIONS} 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/libPusher" "${PODS_ROOT}/Headers/Private/libPusher/Pusher" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/SocketRocket" "${PODS_ROOT}/Headers/Public/libPusher" "${PODS_ROOT}/Headers/Public/libPusher/Pusher" 4 | OTHER_LDFLAGS = -ObjC 5 | PODS_ROOT = ${SRCROOT} 6 | SKIP_INSTALL = YES -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-RNPusherClient-libPusher/Pods-RNPusherClient-libPusher-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_RNPusherClient_libPusher : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_RNPusherClient_libPusher 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-RNPusherClient-libPusher/Pods-RNPusherClient-libPusher-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | #import "Pods-RNPusherClient-environment.h" 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-RNPusherClient-libPusher/Pods-RNPusherClient-libPusher.xcconfig: -------------------------------------------------------------------------------- 1 | PODS_RNPUSHERCLIENT_LIBPUSHER_GCC_PREPROCESSOR_DEFINITIONS = kPTPusherClientLibraryVersion=@\"1.6\" -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-RNPusherClient/Pods-RNPusherClient-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## SocketRocket 5 | 6 | 7 | Copyright 2012 Square Inc. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | 22 | 23 | ## libPusher 24 | 25 | Copyright (c) 2010 Luke Redpath 26 | 27 | The following license applies to all source code unless stated 28 | at the top of the source file. 29 | 30 | Permission is hereby granted, free of charge, to any person 31 | obtaining a copy of this software and associated documentation 32 | files (the "Software"), to deal in the Software without 33 | restriction, including without limitation the rights to use, 34 | copy, modify, merge, publish, distribute, sublicense, and/or sell 35 | copies of the Software, and to permit persons to whom the 36 | Software is furnished to do so, subject to the following 37 | conditions: 38 | 39 | The above copyright notice and this permission notice shall be 40 | included in all copies or substantial portions of the Software. 41 | 42 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 43 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 44 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 45 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 46 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 47 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 48 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 49 | OTHER DEALINGS IN THE SOFTWARE. 50 | Generated by CocoaPods - http://cocoapods.org 51 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-RNPusherClient/Pods-RNPusherClient-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | 18 | Copyright 2012 Square Inc. 19 | 20 | Licensed under the Apache License, Version 2.0 (the "License"); 21 | you may not use this file except in compliance with the License. 22 | You may obtain a copy of the License at 23 | 24 | http://www.apache.org/licenses/LICENSE-2.0 25 | 26 | Unless required by applicable law or agreed to in writing, software 27 | distributed under the License is distributed on an "AS IS" BASIS, 28 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 29 | See the License for the specific language governing permissions and 30 | limitations under the License. 31 | 32 | 33 | Title 34 | SocketRocket 35 | Type 36 | PSGroupSpecifier 37 | 38 | 39 | FooterText 40 | Copyright (c) 2010 Luke Redpath 41 | 42 | The following license applies to all source code unless stated 43 | at the top of the source file. 44 | 45 | Permission is hereby granted, free of charge, to any person 46 | obtaining a copy of this software and associated documentation 47 | files (the "Software"), to deal in the Software without 48 | restriction, including without limitation the rights to use, 49 | copy, modify, merge, publish, distribute, sublicense, and/or sell 50 | copies of the Software, and to permit persons to whom the 51 | Software is furnished to do so, subject to the following 52 | conditions: 53 | 54 | The above copyright notice and this permission notice shall be 55 | included in all copies or substantial portions of the Software. 56 | 57 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 58 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 59 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 60 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 61 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 62 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 63 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 64 | OTHER DEALINGS IN THE SOFTWARE. 65 | Title 66 | libPusher 67 | Type 68 | PSGroupSpecifier 69 | 70 | 71 | FooterText 72 | Generated by CocoaPods - http://cocoapods.org 73 | Title 74 | 75 | Type 76 | PSGroupSpecifier 77 | 78 | 79 | StringsTable 80 | Acknowledgements 81 | Title 82 | Acknowledgements 83 | 84 | 85 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-RNPusherClient/Pods-RNPusherClient-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_RNPusherClient : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_RNPusherClient 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-RNPusherClient/Pods-RNPusherClient-environment.h: -------------------------------------------------------------------------------- 1 | 2 | // To check if a library is compiled with CocoaPods you 3 | // can use the `COCOAPODS` macro definition which is 4 | // defined in the xcconfigs so it is available in 5 | // headers also when they are imported in the client 6 | // project. 7 | 8 | 9 | // SocketRocket 10 | #define COCOAPODS_POD_AVAILABLE_SocketRocket 11 | #define COCOAPODS_VERSION_MAJOR_SocketRocket 0 12 | #define COCOAPODS_VERSION_MINOR_SocketRocket 3 13 | #define COCOAPODS_VERSION_PATCH_SocketRocket 1 14 | 15 | // libPusher 16 | #define COCOAPODS_POD_AVAILABLE_libPusher 17 | #define COCOAPODS_VERSION_MAJOR_libPusher 1 18 | #define COCOAPODS_VERSION_MINOR_libPusher 6 19 | #define COCOAPODS_VERSION_PATCH_libPusher 0 20 | 21 | // libPusher/Core 22 | #define COCOAPODS_POD_AVAILABLE_libPusher_Core 23 | #define COCOAPODS_VERSION_MAJOR_libPusher_Core 1 24 | #define COCOAPODS_VERSION_MINOR_libPusher_Core 6 25 | #define COCOAPODS_VERSION_PATCH_libPusher_Core 0 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-RNPusherClient/Pods-RNPusherClient-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | realpath() { 12 | DIRECTORY=$(cd "${1%/*}" && pwd) 13 | FILENAME="${1##*/}" 14 | echo "$DIRECTORY/$FILENAME" 15 | } 16 | 17 | install_resource() 18 | { 19 | case $1 in 20 | *.storyboard) 21 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}" 22 | ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" 23 | ;; 24 | *.xib) 25 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}" 26 | ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" 27 | ;; 28 | *.framework) 29 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 30 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 31 | echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 32 | rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 33 | ;; 34 | *.xcdatamodel) 35 | echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\"" 36 | xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom" 37 | ;; 38 | *.xcdatamodeld) 39 | echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\"" 40 | xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd" 41 | ;; 42 | *.xcmappingmodel) 43 | echo "xcrun mapc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm\"" 44 | xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm" 45 | ;; 46 | *.xcassets) 47 | ABSOLUTE_XCASSET_FILE=$(realpath "${PODS_ROOT}/$1") 48 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 49 | ;; 50 | /*) 51 | echo "$1" 52 | echo "$1" >> "$RESOURCES_TO_COPY" 53 | ;; 54 | *) 55 | echo "${PODS_ROOT}/$1" 56 | echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY" 57 | ;; 58 | esac 59 | } 60 | 61 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 62 | if [[ "${ACTION}" == "install" ]]; then 63 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 64 | fi 65 | rm -f "$RESOURCES_TO_COPY" 66 | 67 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 68 | then 69 | case "${TARGETED_DEVICE_FAMILY}" in 70 | 1,2) 71 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 72 | ;; 73 | 1) 74 | TARGET_DEVICE_ARGS="--target-device iphone" 75 | ;; 76 | 2) 77 | TARGET_DEVICE_ARGS="--target-device ipad" 78 | ;; 79 | *) 80 | TARGET_DEVICE_ARGS="--target-device mac" 81 | ;; 82 | esac 83 | 84 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 85 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 86 | while read line; do 87 | if [[ $line != "`realpath $PODS_ROOT`*" ]]; then 88 | XCASSET_FILES+=("$line") 89 | fi 90 | done <<<"$OTHER_XCASSETS" 91 | 92 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 93 | fi 94 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-RNPusherClient/Pods-RNPusherClient.debug.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 kPTPusherClientLibraryVersion=@\"1.6\" 2 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/SocketRocket" "${PODS_ROOT}/Headers/Public/libPusher" "${PODS_ROOT}/Headers/Public/libPusher/Pusher" 3 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/SocketRocket" -isystem "${PODS_ROOT}/Headers/Public/libPusher" -isystem "${PODS_ROOT}/Headers/Public/libPusher/Pusher" 4 | OTHER_LDFLAGS = $(inherited) -ObjC -l"Pods-RNPusherClient-SocketRocket" -l"Pods-RNPusherClient-libPusher" -l"icucore" -framework "CFNetwork" -framework "Security" 5 | OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS) 6 | PODS_ROOT = ${SRCROOT}/Pods -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-RNPusherClient/Pods-RNPusherClient.release.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 kPTPusherClientLibraryVersion=@\"1.6\" 2 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/SocketRocket" "${PODS_ROOT}/Headers/Public/libPusher" "${PODS_ROOT}/Headers/Public/libPusher/Pusher" 3 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/SocketRocket" -isystem "${PODS_ROOT}/Headers/Public/libPusher" -isystem "${PODS_ROOT}/Headers/Public/libPusher/Pusher" 4 | OTHER_LDFLAGS = $(inherited) -ObjC -l"Pods-RNPusherClient-SocketRocket" -l"Pods-RNPusherClient-libPusher" -l"icucore" -framework "CFNetwork" -framework "Security" 5 | OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS) 6 | PODS_ROOT = ${SRCROOT}/Pods -------------------------------------------------------------------------------- /Pods/libPusher/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 Luke Redpath 2 | 3 | The following license applies to all source code unless stated 4 | at the top of the source file. 5 | 6 | Permission is hereby granted, free of charge, to any person 7 | obtaining a copy of this software and associated documentation 8 | files (the "Software"), to deal in the Software without 9 | restriction, including without limitation the rights to use, 10 | copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the 12 | Software is furnished to do so, subject to the following 13 | conditions: 14 | 15 | The above copyright notice and this permission notice shall be 16 | included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Pods/libPusher/Library/NSDictionary+QueryString.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+QueryString.m 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 23/04/2010. 6 | // Copyright 2010 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import "NSDictionary+QueryString.h" 10 | 11 | 12 | @implementation NSDictionary (QueryString) 13 | 14 | - (NSString *)sortedQueryString; 15 | { 16 | NSMutableArray *parts = [[NSMutableArray alloc] initWithCapacity:[[self allKeys] count]]; 17 | NSArray *sortedKeys = [[self allKeys] sortedArrayUsingSelector:@selector(localizedCompare:)]; 18 | for (NSString *key in sortedKeys) { 19 | NSString *part = [[NSString alloc] initWithFormat:@"%@=%@", key, [self valueForKey:key]]; 20 | [parts addObject:part]; 21 | } 22 | NSString *queryString = [parts componentsJoinedByString:@"&"]; 23 | 24 | return queryString; 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/NSString+Hashing.m: -------------------------------------------------------------------------------- 1 | #import "NSString+Hashing.h" 2 | #import 3 | #import 4 | 5 | @implementation NSString (Hashing) 6 | 7 | - (NSString *)MD5Hash; 8 | { 9 | const char *cStr = [self UTF8String]; 10 | unsigned char result[CC_MD5_DIGEST_LENGTH]; 11 | 12 | CC_MD5( cStr, (CC_LONG)strlen(cStr), result ); 13 | 14 | return [NSString stringWithFormat: 15 | @"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", 16 | result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7], 17 | result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15] 18 | ]; 19 | } 20 | 21 | 22 | - (NSString *)HMACDigestUsingSecretKey:(id)secretKey 23 | { 24 | const char *cKey = [secretKey cStringUsingEncoding:NSASCIIStringEncoding]; 25 | const char *cData = [self cStringUsingEncoding:NSASCIIStringEncoding]; 26 | 27 | unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH]; 28 | 29 | CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC); 30 | 31 | NSMutableString *result = [[NSMutableString alloc] init]; 32 | for (int i = 0; i < sizeof(cHMAC); i++) { 33 | [result appendFormat:@"%02x", cHMAC[i] & 0xff]; 34 | } 35 | NSString *digest = [result copy]; 36 | 37 | return digest; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTBlockEventListener.m: -------------------------------------------------------------------------------- 1 | // 2 | // PTBlockEventListener.m 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 14/08/2011. 6 | // Copyright 2011 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import "PTBlockEventListener.h" 10 | 11 | @interface PTBlockEventListener : NSObject 12 | @end 13 | 14 | @implementation PTBlockEventListener { 15 | PTBlockEventListenerBlock _block; 16 | dispatch_queue_t _queue; 17 | BOOL _invalid; 18 | } 19 | 20 | - (id)initWithBlock:(PTBlockEventListenerBlock)aBlock dispatchQueue:(dispatch_queue_t)aQueue 21 | { 22 | NSParameterAssert(aBlock); 23 | 24 | if ((self = [super init])) { 25 | _block = [aBlock copy]; 26 | _queue = aQueue; 27 | _invalid = NO; 28 | #if !OS_OBJECT_USE_OBJC 29 | dispatch_retain(_queue); 30 | #endif 31 | } 32 | return self; 33 | } 34 | 35 | - (void)dealloc 36 | { 37 | #if !OS_OBJECT_USE_OBJC 38 | dispatch_release(_queue); 39 | #endif 40 | } 41 | 42 | - (void)invalidate 43 | { 44 | _invalid = YES; 45 | } 46 | 47 | - (void)dispatchEvent:(PTPusherEvent *)event 48 | { 49 | dispatch_async(_queue, ^{ 50 | if (!_invalid) { 51 | _block(event); 52 | } 53 | }); 54 | } 55 | 56 | @end 57 | 58 | @implementation PTPusherEventDispatcher (PTBlockEventFactory) 59 | 60 | - (PTPusherEventBinding *)addEventListenerForEventNamed:(NSString *)eventName 61 | block:(PTBlockEventListenerBlock)block 62 | queue:(dispatch_queue_t)queue 63 | { 64 | PTBlockEventListener *listener = [[PTBlockEventListener alloc] initWithBlock:block dispatchQueue:queue]; 65 | return [self addEventListener:listener forEventNamed:eventName]; 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTEventListener.h: -------------------------------------------------------------------------------- 1 | // 2 | // PTEventListener.h 3 | // PusherEvents 4 | // 5 | // Created by Luke Redpath on 22/03/2010. 6 | // Copyright 2010 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @class PTPusherEvent; 13 | 14 | @protocol PTEventListener 15 | 16 | - (void)dispatchEvent:(PTPusherEvent *)event; 17 | 18 | @optional 19 | 20 | - (void)invalidate; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTJSON.m: -------------------------------------------------------------------------------- 1 | // 2 | // PTJSON.m 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 30/03/2012. 6 | // Copyright (c) 2012 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import "PTJSON.h" 10 | #import "PTPusherMacros.h" 11 | 12 | @interface PTNSJSONParser : NSObject 13 | + (id)NSJSONParser; 14 | @end 15 | 16 | @implementation PTJSON 17 | 18 | + (id)JSONParser 19 | { 20 | return [PTNSJSONParser NSJSONParser]; 21 | } 22 | 23 | @end 24 | 25 | @implementation PTNSJSONParser 26 | 27 | + (id)NSJSONParser 28 | { 29 | PT_DEFINE_SHARED_INSTANCE_USING_BLOCK(^{ 30 | return [[self alloc] init]; 31 | }); 32 | } 33 | 34 | - (NSData *)JSONDataFromObject:(id)object 35 | { 36 | return [NSJSONSerialization dataWithJSONObject:object options:0 error:nil]; 37 | } 38 | 39 | - (NSString *)JSONStringFromObject:(id)object 40 | { 41 | return [[NSString alloc] initWithData:[self JSONDataFromObject:object] encoding:NSUTF8StringEncoding]; 42 | } 43 | 44 | - (id)objectFromJSONData:(NSData *)data 45 | { 46 | return [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; 47 | } 48 | 49 | - (id)objectFromJSONString:(NSString *)string 50 | { 51 | return [self objectFromJSONData:[string dataUsingEncoding:NSUTF8StringEncoding]]; 52 | } 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTPusher+Testing.h: -------------------------------------------------------------------------------- 1 | // 2 | // PTPusher+Testing.h 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 11/05/2012. 6 | // Copyright (c) 2012 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "PTPusher.h" 11 | 12 | extern NSString *const PTPusherAuthorizationBypassURL; 13 | 14 | @interface PTPusher (Testing) 15 | 16 | - (void)enableChannelAuthorizationBypassMode; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTPusher+Testing.m: -------------------------------------------------------------------------------- 1 | // 2 | // PTPusher+Testing.m 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 11/05/2012. 6 | // Copyright (c) 2012 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import "PTPusher+Testing.h" 10 | #import "PTPusherChannelAuthorizationOperation.h" 11 | 12 | NSString *const PTPusherAuthorizationBypassURL = @"libpusher://auth/bypass/url"; 13 | 14 | @implementation PTPusher (Testing) 15 | 16 | - (void)enableChannelAuthorizationBypassMode 17 | { 18 | self.authorizationURL = [NSURL URLWithString:PTPusherAuthorizationBypassURL]; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTPusher.h: -------------------------------------------------------------------------------- 1 | // 2 | // PTPusher.h 3 | // PusherEvents 4 | // 5 | // Created by Luke Redpath on 22/03/2010. 6 | // Copyright 2010 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "PTPusherDelegate.h" 11 | #import "PTPusherConnection.h" 12 | #import "PTPusherEventPublisher.h" 13 | #import "PTPusherPresenceChannelDelegate.h" 14 | 15 | /** The name of the notification posted when PTPusher receives an event. 16 | */ 17 | extern NSString *const PTPusherEventReceivedNotification; 18 | 19 | /** The key of the PTPusherEvent object in the PTPusherEventReceivedNotification userInfo dictionary. 20 | */ 21 | extern NSString *const PTPusherEventUserInfoKey; 22 | 23 | /** The error domain for all non-fatal PTPusher errors. 24 | * 25 | * These will be any errors not in the range of 4000-4099. 26 | * 27 | * See: http://pusher.com/docs/pusher_protocol#error-codes 28 | */ 29 | extern NSString *const PTPusherErrorDomain; 30 | 31 | /** The error domain for all fatal PTPusher errors. 32 | * 33 | * These will be any errors in the range of 4000-4099. If your 34 | * connection fails or disconnects with one of these errors, you 35 | * will typically not be able to reconnect immediately (or at all). 36 | * 37 | * See: http://pusher.com/docs/pusher_protocol#error-codes 38 | */ 39 | extern NSString *const PTPusherFatalErrorDomain; 40 | 41 | /** The key for any underlying PTPusherEvent associated with a PTPusher error's userInfo dictionary. 42 | */ 43 | extern NSString *const PTPusherErrorUnderlyingEventKey; 44 | 45 | @class PTPusherChannel; 46 | @class PTPusherPresenceChannel; 47 | @class PTPusherPrivateChannel; 48 | @class PTPusherEventDispatcher; 49 | 50 | /** A PTPusher object provides a high level API for communicating with the Pusher service. 51 | 52 | A single instance of `PTPusher` can be used to connect to the service, subscribe to channels and send 53 | events. 54 | 55 | To create an instance of PTPusher, you will need your Pusher API key. This can be obtained from your account 56 | dashboard. 57 | 58 | PTPusher's delegate methods allow an object to receive important events in the client and connection's 59 | lifecycle, such as connection, disconnection, reconnection and channel subscribe/unsubscribe events. 60 | 61 | Whilst PTPusher exposes it's connection object as a readonly property, there is no need to manage or 62 | create this connection yourself. The connection can be queried for it's current connection state and 63 | socket ID if needed. 64 | 65 | PTPusher aims to mirror the Pusher Javascript client API as much as possible although whilst the 66 | Javascript API uses event binding for any system events, such as channel subscription 67 | libPusher uses standard Cocoa and Objective-C patterns such as delegation and notification where 68 | it makes sense to do so. 69 | 70 | PTPusher will attempt to try and remain connected whenever possible. If the connection disconnects, 71 | then depending on the error code returned, it will either try to reconnect immediately, reconnect after 72 | a configured delay or not reconnect at all. See the project README for more information on this. 73 | 74 | Note: due to various problems people have had connecting to Pusher without SSL over a 3G connection, 75 | it is highly recommend that you use SSL. For this reason, SSL is enabled by default. 76 | */ 77 | @interface PTPusher : NSObject 78 | 79 | ///------------------------------------------------------------------------------------/ 80 | /// @name Properties 81 | ///------------------------------------------------------------------------------------/ 82 | 83 | /** The object that acts as the delegate for the receiving instance. 84 | 85 | The delegate must implement the PTPusherDelegate protocol. The delegate is not retained. 86 | */ 87 | @property (nonatomic, weak) id delegate; 88 | 89 | /** Specifies the delay between reconnection attempts. Defaults to 5 seconds. 90 | */ 91 | @property (nonatomic, assign) NSTimeInterval reconnectDelay; 92 | 93 | /** The connection object for this client. 94 | 95 | Each instance uses a single connection only. Most clients will likely only ever need a single 96 | PTPusher object and therefore a single connection. 97 | 98 | The connection is exposed to provide access to it's socketID and connection state. Clients 99 | should not attempt to manage this connection directly. 100 | */ 101 | @property (nonatomic, strong, readonly) PTPusherConnection *connection; 102 | 103 | /** The authorization URL for private subscriptions. 104 | 105 | All private channels (including presence channels) require authorization in order to subscribe. 106 | 107 | Authorization happens on your own server. When subscribing to a private or presence channel, 108 | an authorization POST request will be sent to the URL specified by this property. 109 | 110 | Attempting to subscribe to a private or presence channel without setting this property will 111 | result in an assertion error. 112 | 113 | For more information on channel authorization, [see the Pusher documentation website](http://pusher.com/docs/authenticating_users). 114 | */ 115 | @property (nonatomic, strong) NSURL *authorizationURL; 116 | 117 | ///------------------------------------------------------------------------------------/ 118 | /// @name Creating new instances 119 | ///------------------------------------------------------------------------------------/ 120 | 121 | /** Initialises a new instance. This is the designated initialiser. 122 | * 123 | * Clients should typically use one of the factory methods provided, which will configure the 124 | * connection object for you using the standard Pusher host and port. 125 | * 126 | * If you need to connect to Pusher using an alternative endpoint URL, e.g. for testing 127 | * purposes, then you can initialise an instance of `PTPusherConnection` with an appropriate 128 | * URL and pass it into this method. 129 | * 130 | * @param connection An initialised connection for this instance. 131 | */ 132 | - (id)initWithConnection:(PTPusherConnection *)connection; 133 | 134 | /** Returns a new PTPusher instance with a connection configured with the given key. 135 | 136 | @param key Your application's API key. It can be found in the API Access section of your application within the Pusher user dashboard. 137 | @param delegate The delegate for this instance 138 | @param isEncrypted If yes, a secure connection over SSL will be established. 139 | */ 140 | + (id)pusherWithKey:(NSString *)key delegate:(id)delegate encrypted:(BOOL)isEncrypted; 141 | 142 | /** Returns a new PTPusher instance with a connection configured with the given key and allows to set different cluster 143 | 144 | @param key Your application's API key. It can be found in the API Access section of your application within the Pusher user dashboard. 145 | @param delegate The delegate for this instance 146 | @param isEncrypted If yes, a secure connection over SSL will be established. 147 | @param cluster If set, connects to the provided cluster 148 | */ 149 | 150 | + (id)pusherWithKey:(NSString *)key delegate:(id)delegate encrypted:(BOOL)isEncrypted cluster:(NSString *) cluster; 151 | 152 | /** Returns a new PTPusher instance with an connection configured with the given key. 153 | 154 | Instances created using this method will be encrypted by default. This requires SSL access on your account, 155 | which is generally recommended for mobile connections. 156 | 157 | @param key Your application's API key. It can be found in the API Access section of your application within the Pusher user dashboard. 158 | @param delegate The delegate for this instance 159 | */ 160 | + (id)pusherWithKey:(NSString *)key delegate:(id)delegate; 161 | 162 | ///------------------------------------------------------------------------------------/ 163 | /// @name Managing the connection 164 | ///------------------------------------------------------------------------------------/ 165 | 166 | /** Establishes a connection to the Pusher server. 167 | 168 | If already connected, this method does nothing. 169 | */ 170 | - (void)connect; 171 | 172 | /** Disconnects from the Pusher server. 173 | 174 | If already disconnected, this method does nothing. 175 | */ 176 | - (void)disconnect; 177 | 178 | ///------------------------------------------------------------------------------------/ 179 | /// @name Subscribing to channels 180 | ///------------------------------------------------------------------------------------/ 181 | 182 | /** Subscribes to the named channel. 183 | 184 | This method can be used to subscribe to any type of channel, including private and 185 | presence channels by including the appropriate channel name prefix. 186 | 187 | Note: this method returns the channel object immediately, but it might not yet be 188 | subscribed - subscription is asynchronous. You do not have to wait for a channel 189 | to become subscribed before setting up event bindings. If you care about when the 190 | channel is subscribed, you can use key-value observing on it's `isSubscribed` 191 | property or implement the appropriate `PTPusherDelegate` method. 192 | 193 | It is valid to call this (or any of the other subscribe methods) while the client is 194 | not connected. All channels default to unsubscribed and any subcribed channels will 195 | become implicitly unsubscribed if the client disconnects. When the client connects, 196 | all channels will be re-subscribed to automatically. 197 | 198 | When you subscribe to a channel, `PTPusher` keeps a strong reference to that channel 199 | and maintains that reference until the channel is explicitly unsubscribed (by calling 200 | `-[PTPusherChannel unsubscribe]`. 201 | 202 | If you maintain your own strong reference to the returned channel object, you should 203 | be aware that once unsubscribed, the object will no longer be of any use. For this 204 | reason you should be wary of passing around strong references to channels that you 205 | may unsubscribe from. 206 | 207 | For more information on channel lifetime, see the README. 208 | 209 | @param name The name of the channel to subscribe to. 210 | @returns The channel object. 211 | */ 212 | - (PTPusherChannel *)subscribeToChannelNamed:(NSString *)name; 213 | 214 | /** Subscribes to the named private channel. 215 | 216 | The "private-" prefix should be excluded from the name; it will be added automatically. 217 | 218 | @param name The name of the channel (without the private prefix) to subscribe to. 219 | */ 220 | - (PTPusherPrivateChannel *)subscribeToPrivateChannelNamed:(NSString *)name; 221 | 222 | /** Subscribes to the named presence channel. 223 | 224 | The "presence-" prefix should be excluded from the name; it will be added automatically. 225 | 226 | @param name The name of the channel (without the presence prefix) to subscribe to. 227 | */ 228 | - (PTPusherPresenceChannel *)subscribeToPresenceChannelNamed:(NSString *)name; 229 | 230 | /** Subscribes to the named presence channel. 231 | 232 | The "presence-" prefix should be excluded from the name; it will be added automatically. 233 | 234 | Whilst the presence delegate can be set on the channel after it is returned, to ensure 235 | events are not missed, it is advised that you call this method and specify a delegate. The 236 | delegate will be assigned before subscription happens. 237 | 238 | @param name The name of the channel (without the presence prefix) to subscribe to. 239 | @param presenceDelegate The presence delegate for this channel. 240 | */ 241 | - (PTPusherPresenceChannel *)subscribeToPresenceChannelNamed:(NSString *)name delegate:(id)presenceDelegate; 242 | 243 | /** Returns a previously subscribed channel with the given name. 244 | 245 | If the channel specified has not been subscribed to previously, or has been explicilty 246 | unsubscribed from, this will return nil. 247 | 248 | This method will return channels that have become implicitly unsubscribed from if the 249 | client has disconnected. 250 | 251 | @param name The name of the channel required. 252 | */ 253 | - (PTPusherChannel *)channelNamed:(NSString *)name; 254 | 255 | ///------------------------------------------------------------------------------------/ 256 | /// @name Publishing events 257 | ///------------------------------------------------------------------------------------/ 258 | 259 | /** Sends an event directly over the connection's socket. 260 | 261 | Whilst Pusher provides a REST API for publishing events, it also supports the sending of 262 | events directly from clients over the client's existing connection. 263 | 264 | Client events have the following restrictions: 265 | 266 | + The user must be subscribed to the channel that the event is being triggered on. 267 | 268 | + Client events can only be triggered on private and presence channels because they require authentication. 269 | 270 | + Client events must be prefixed by client-. Events with any other prefix will be rejected by the Pusher server, as will events sent to channels to which the client is not subscribed. 271 | 272 | This method does nothing to enforce the first two restrictions. It is instead recommended that 273 | you use the `PTPusherChannel` event triggering API rather than calling this method directly. 274 | 275 | @warning Note: This Pusher feature is currently in beta and requires enabling on your account. 276 | */ 277 | - (void)sendEventNamed:(NSString *)name data:(id)data channel:(NSString *)channelName; 278 | 279 | @end 280 | 281 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTPusher.m: -------------------------------------------------------------------------------- 1 | // 2 | // PTPusher.m 3 | // PusherEvents 4 | // 5 | // Created by Luke Redpath on 22/03/2010. 6 | // Copyright 2010 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import "PTPusher.h" 10 | #import "PTEventListener.h" 11 | #import "PTPusherEvent.h" 12 | #import "PTPusherChannel.h" 13 | #import "PTPusherEventDispatcher.h" 14 | #import "PTTargetActionEventListener.h" 15 | #import "PTBlockEventListener.h" 16 | #import "PTPusherErrors.h" 17 | #import "PTPusherChannelAuthorizationOperation.h" 18 | #import "PTPusherChannel_Private.h" 19 | 20 | #define kPUSHER_HOST @"ws.pusherapp.com" 21 | 22 | typedef NS_ENUM(NSUInteger, PTPusherAutoReconnectMode) { 23 | PTPusherAutoReconnectModeNoReconnect, 24 | PTPusherAutoReconnectModeReconnectImmediately, 25 | PTPusherAutoReconnectModeReconnectWithConfiguredDelay, 26 | PTPusherAutoReconnectModeReconnectWithBackoffDelay 27 | }; 28 | 29 | NSURL *PTPusherConnectionURL(NSString *host, NSString *key, NSString *clientID, BOOL secure); 30 | 31 | NSString *const PTPusherEventReceivedNotification = @"PTPusherEventReceivedNotification"; 32 | NSString *const PTPusherEventUserInfoKey = @"PTPusherEventUserInfoKey"; 33 | NSString *const PTPusherErrorDomain = @"PTPusherErrorDomain"; 34 | NSString *const PTPusherFatalErrorDomain = @"PTPusherFatalErrorDomain"; 35 | NSString *const PTPusherErrorUnderlyingEventKey = @"PTPusherErrorUnderlyingEventKey"; 36 | 37 | /** The Pusher protocol version, used to determined which features 38 | are supported. 39 | */ 40 | #define kPTPusherClientProtocolVersion 6 41 | 42 | NSURL *PTPusherConnectionURL(NSString *host, NSString *key, NSString *clientID, BOOL encrypted) 43 | { 44 | NSString *scheme = ((encrypted == YES) ? @"wss" : @"ws"); 45 | NSString *URLString = [NSString stringWithFormat:@"%@://%@/app/%@?client=%@&protocol=%d&version=%@", 46 | scheme, host, key, clientID, kPTPusherClientProtocolVersion, kPTPusherClientLibraryVersion]; 47 | return [NSURL URLWithString:URLString]; 48 | } 49 | 50 | #define kPTPusherDefaultReconnectDelay 5.0 51 | 52 | @interface PTPusher () 53 | @property (nonatomic, strong, readwrite) PTPusherConnection *connection; 54 | @end 55 | 56 | #pragma mark - 57 | 58 | @implementation PTPusher { 59 | NSOperationQueue *authorizationQueue; 60 | NSUInteger _numberOfReconnectAttempts; 61 | NSUInteger _maximumNumberOfReconnectAttempts; 62 | PTPusherEventDispatcher *dispatcher; 63 | NSMutableDictionary *channels; 64 | } 65 | 66 | - (id)initWithConnection:(PTPusherConnection *)connection 67 | { 68 | if (self = [super init]) { 69 | dispatcher = [[PTPusherEventDispatcher alloc] init]; 70 | channels = [[NSMutableDictionary alloc] init]; 71 | 72 | authorizationQueue = [[NSOperationQueue alloc] init]; 73 | authorizationQueue.maxConcurrentOperationCount = 5; 74 | authorizationQueue.name = @"com.pusher.libPusher.authorizationQueue"; 75 | 76 | self.connection = connection; 77 | self.connection.delegate = self; 78 | self.reconnectDelay = kPTPusherDefaultReconnectDelay; 79 | 80 | /* Three reconnection attempts should be more than enough attempts 81 | * to reconnect where the user has simply locked their device or 82 | * backgrounded the app. 83 | * 84 | * If there is no internet connection, we will only end up retrying 85 | * once as after the first failure we will no longer auto-retry. 86 | * 87 | * We may consider making this user-customisable in future but not 88 | * for now. 89 | */ 90 | _maximumNumberOfReconnectAttempts = 3; 91 | } 92 | return self; 93 | } 94 | 95 | + (id)pusherWithKey:(NSString *)key delegate:(id)delegate 96 | { 97 | return [self pusherWithKey:key delegate:delegate encrypted:YES]; 98 | } 99 | 100 | + (id)pusherWithKey:(NSString *)key delegate:(id)delegate encrypted:(BOOL)isEncrypted 101 | { 102 | return [self pusherWithKey:(NSString *)key delegate:(id)delegate encrypted:(BOOL)isEncrypted cluster:(NSString *) nil]; 103 | } 104 | 105 | + (id)pusherWithKey:(NSString *)key delegate:(id)delegate encrypted:(BOOL)isEncrypted cluster:(NSString *) cluster 106 | { 107 | NSString * hostURL; 108 | if ([cluster length] == 0) { 109 | hostURL = kPUSHER_HOST; 110 | } else { 111 | hostURL = [NSString stringWithFormat:@"ws-%@.pusher.com", cluster]; 112 | } 113 | 114 | NSURL *serviceURL = PTPusherConnectionURL(hostURL, key, @"libPusher", isEncrypted); 115 | PTPusherConnection *connection = [[PTPusherConnection alloc] initWithURL:serviceURL]; 116 | PTPusher *pusher = [[self alloc] initWithConnection:connection]; 117 | pusher.delegate = delegate; 118 | return pusher; 119 | } 120 | 121 | - (void)dealloc; 122 | { 123 | [_connection setDelegate:nil]; 124 | [_connection disconnect]; 125 | } 126 | 127 | #pragma mark - Connection management 128 | 129 | - (void)setReconnectDelay:(NSTimeInterval)reconnectDelay 130 | { 131 | _reconnectDelay = MAX(reconnectDelay, 1); 132 | } 133 | 134 | - (void)connect 135 | { 136 | _numberOfReconnectAttempts = 0; 137 | [self.connection connect]; 138 | } 139 | 140 | - (void)disconnect 141 | { 142 | [self.connection disconnect]; 143 | } 144 | 145 | #pragma mark - Binding to events 146 | 147 | - (PTPusherEventBinding *)bindToEventNamed:(NSString *)eventName target:(id)target action:(SEL)selector 148 | { 149 | return [dispatcher addEventListenerForEventNamed:eventName target:target action:selector]; 150 | } 151 | 152 | - (PTPusherEventBinding *)bindToEventNamed:(NSString *)eventName handleWithBlock:(PTPusherEventBlockHandler)block 153 | { 154 | return [self bindToEventNamed:eventName handleWithBlock:block queue:dispatch_get_main_queue()]; 155 | } 156 | 157 | - (PTPusherEventBinding *)bindToEventNamed:(NSString *)eventName handleWithBlock:(PTPusherEventBlockHandler)block queue:(dispatch_queue_t)queue 158 | { 159 | return [dispatcher addEventListenerForEventNamed:eventName block:block queue:queue]; 160 | } 161 | 162 | - (void)removeBinding:(PTPusherEventBinding *)binding 163 | { 164 | [dispatcher removeBinding:binding]; 165 | } 166 | 167 | - (void)removeAllBindings 168 | { 169 | [dispatcher removeAllBindings]; 170 | } 171 | 172 | #pragma mark - Subscribing to channels 173 | 174 | - (PTPusherChannel *)subscribeToChannelNamed:(NSString *)name 175 | { 176 | PTPusherChannel *channel = channels[name]; 177 | if (channel == nil) { 178 | channel = [PTPusherChannel channelWithName:name pusher:self]; 179 | channels[name] = channel; 180 | } 181 | // private/presence channels require a socketID to authenticate 182 | if (self.connection.isConnected && self.connection.socketID) { 183 | [self subscribeToChannel:channel]; 184 | } 185 | return channel; 186 | } 187 | 188 | - (PTPusherPrivateChannel *)subscribeToPrivateChannelNamed:(NSString *)name 189 | { 190 | return (PTPusherPrivateChannel *)[self subscribeToChannelNamed:[NSString stringWithFormat:@"private-%@", name]]; 191 | } 192 | 193 | - (PTPusherPresenceChannel *)subscribeToPresenceChannelNamed:(NSString *)name 194 | { 195 | return (PTPusherPresenceChannel *)[self subscribeToChannelNamed:[NSString stringWithFormat:@"presence-%@", name]]; 196 | } 197 | 198 | - (PTPusherPresenceChannel *)subscribeToPresenceChannelNamed:(NSString *)name delegate:(id)presenceDelegate 199 | { 200 | PTPusherPresenceChannel *channel = [self subscribeToPresenceChannelNamed:name]; 201 | channel.presenceDelegate = presenceDelegate; 202 | return channel; 203 | } 204 | 205 | - (PTPusherChannel *)channelNamed:(NSString *)name 206 | { 207 | return channels[name]; 208 | } 209 | 210 | /* This is only called when a client explicitly unsubscribes from a channel 211 | * by calling either [channel unsubscribe] or using the deprecated API 212 | * [client unsubscribeFromChannel:]. 213 | * 214 | * This effectively ends the lifetime of a channel: the client will remove it 215 | * from it's channels collection and all bindings will be removed. If no other 216 | * code outside of libPusher has a strong reference to the channel, it will 217 | * be deallocated. 218 | * 219 | * This is different to implicit unsubscribes (where the connection has been lost) 220 | * where the channel will object will remain and be re-subscribed when connection 221 | * is re-established. 222 | * 223 | * A pusher:unsubscribe event will only be sent if there is a connection, otherwise 224 | * it's not necessary as the channel is already implicitly unsubscribed due to the 225 | * disconnection. 226 | */ 227 | - (void)__unsubscribeFromChannel:(PTPusherChannel *)channel 228 | { 229 | NSParameterAssert(channel != nil); 230 | 231 | [channel removeAllBindings]; 232 | 233 | if (self.connection.isConnected) { 234 | [self sendEventNamed:@"pusher:unsubscribe" 235 | data:@{@"channel": channel.name}]; 236 | } 237 | 238 | [channels removeObjectForKey:channel.name]; 239 | 240 | if ([self.delegate respondsToSelector:@selector(pusher:didUnsubscribeFromChannel:)]) { 241 | [self.delegate pusher:self didUnsubscribeFromChannel:channel]; 242 | } 243 | } 244 | 245 | - (void)subscribeToChannel:(PTPusherChannel *)channel 246 | { 247 | [channel authorizeWithCompletionHandler:^(BOOL isAuthorized, NSDictionary *authData, NSError *error) { 248 | if (isAuthorized && self.connection.isConnected) { 249 | if ([self.delegate respondsToSelector:@selector(pusher:authorizationPayloadFromResponseData:)]) { 250 | authData = [self.delegate pusher:self authorizationPayloadFromResponseData:authData]; 251 | } 252 | [channel subscribeWithAuthorization:authData]; 253 | } 254 | else { 255 | if (error == nil) { 256 | error = [NSError errorWithDomain:PTPusherErrorDomain code:PTPusherSubscriptionUnknownAuthorisationError userInfo:nil]; 257 | } 258 | 259 | if ([self.delegate respondsToSelector:@selector(pusher:didFailToSubscribeToChannel:withError:)]) { 260 | [self.delegate pusher:self didFailToSubscribeToChannel:channel withError:error]; 261 | } 262 | } 263 | }]; 264 | } 265 | 266 | - (void)subscribeAll 267 | { 268 | for (PTPusherChannel *channel in [channels allValues]) { 269 | [self subscribeToChannel:channel]; 270 | } 271 | } 272 | 273 | #pragma mark - Sending events 274 | 275 | - (void)sendEventNamed:(NSString *)name data:(id)data 276 | { 277 | [self sendEventNamed:name data:data channel:nil]; 278 | } 279 | 280 | - (void)sendEventNamed:(NSString *)name data:(id)data channel:(NSString *)channelName 281 | { 282 | NSParameterAssert(name); 283 | 284 | if (self.connection.isConnected == NO) { 285 | NSLog(@"Warning: attempting to send event while disconnected. Event will not be sent."); 286 | return; 287 | } 288 | 289 | NSMutableDictionary *payload = [NSMutableDictionary dictionary]; 290 | payload[PTPusherEventKey] = name; 291 | 292 | if (data) { 293 | payload[PTPusherDataKey] = data; 294 | } 295 | 296 | if (channelName) { 297 | payload[PTPusherChannelKey] = channelName; 298 | } 299 | [self.connection send:payload]; 300 | } 301 | 302 | #pragma mark - PTPusherConnection delegate methods 303 | 304 | - (BOOL)pusherConnectionWillConnect:(PTPusherConnection *)connection 305 | { 306 | if ([self.delegate respondsToSelector:@selector(pusher:connectionWillConnect:)]) { 307 | return [self.delegate pusher:self connectionWillConnect:connection]; 308 | } 309 | return YES; 310 | } 311 | 312 | - (void)pusherConnectionDidConnect:(PTPusherConnection *)connection 313 | { 314 | _numberOfReconnectAttempts = 0; 315 | 316 | if ([self.delegate respondsToSelector:@selector(pusher:connectionDidConnect:)]) { 317 | [self.delegate pusher:self connectionDidConnect:connection]; 318 | } 319 | 320 | [self subscribeAll]; 321 | } 322 | 323 | - (void)pusherConnection:(PTPusherConnection *)connection didDisconnectWithCode:(NSInteger)errorCode reason:(NSString *)reason wasClean:(BOOL)wasClean 324 | { 325 | NSError *error = nil; 326 | 327 | if (errorCode > 0) { 328 | if (reason == nil) { 329 | reason = @"Unknown error"; // not sure what could cause this to be nil, but just playing it safe 330 | } 331 | 332 | NSString *errorDomain = PTPusherErrorDomain; 333 | 334 | if (errorCode >= 400 && errorCode <= 4099) { 335 | errorDomain = PTPusherFatalErrorDomain; 336 | } 337 | 338 | // check for error codes based on the Pusher Websocket protocol see http://pusher.com/docs/pusher_protocol 339 | error = [NSError errorWithDomain:errorDomain code:errorCode userInfo:@{@"reason": reason}]; 340 | 341 | // 4000-4099 -> The connection SHOULD NOT be re-established unchanged. 342 | if (errorCode >= 4000 && errorCode <= 4099) { 343 | [self handleDisconnection:connection error:error reconnectMode:PTPusherAutoReconnectModeNoReconnect]; 344 | } else 345 | // 4200-4299 -> The connection SHOULD be re-established immediately. 346 | if(errorCode >= 4200 && errorCode <= 4299) { 347 | [self handleDisconnection:connection error:error reconnectMode:PTPusherAutoReconnectModeReconnectImmediately]; 348 | } 349 | 350 | else { 351 | // i.e. 4100-4199 -> The connection SHOULD be re-established after backing off. 352 | [self handleDisconnection:connection error:error reconnectMode:PTPusherAutoReconnectModeReconnectWithBackoffDelay]; 353 | } 354 | } 355 | else { 356 | [self handleDisconnection:connection error:error reconnectMode:PTPusherAutoReconnectModeReconnectWithConfiguredDelay]; 357 | } 358 | } 359 | 360 | - (void)pusherConnection:(PTPusherConnection *)connection didFailWithError:(NSError *)error wasConnected:(BOOL)wasConnected 361 | { 362 | if (wasConnected) { 363 | [self handleDisconnection:connection error:error reconnectMode:PTPusherAutoReconnectModeReconnectImmediately]; 364 | } 365 | else { 366 | if ([self.delegate respondsToSelector:@selector(pusher:connection:failedWithError:)]) { 367 | [self.delegate pusher:self connection:connection failedWithError:error]; 368 | } 369 | } 370 | } 371 | 372 | - (void)pusherConnection:(PTPusherConnection *)connection didReceiveEvent:(PTPusherEvent *)event 373 | { 374 | if ([event isKindOfClass:[PTPusherErrorEvent class]]) { 375 | if ([self.delegate respondsToSelector:@selector(pusher:didReceiveErrorEvent:)]) { 376 | [self.delegate pusher:self didReceiveErrorEvent:(PTPusherErrorEvent *)event]; 377 | } 378 | } 379 | 380 | if (event.channel) { 381 | [channels[event.channel] dispatchEvent:event]; 382 | } 383 | [dispatcher dispatchEvent:event]; 384 | 385 | [[NSNotificationCenter defaultCenter] 386 | postNotificationName:PTPusherEventReceivedNotification 387 | object:self 388 | userInfo:@{PTPusherEventUserInfoKey: event}]; 389 | } 390 | 391 | - (void)handleDisconnection:(PTPusherConnection *)connection error:(NSError *)error reconnectMode:(PTPusherAutoReconnectMode)reconnectMode 392 | { 393 | [authorizationQueue cancelAllOperations]; 394 | 395 | for (PTPusherChannel *channel in [channels allValues]) { 396 | [channel handleDisconnect]; 397 | } 398 | 399 | BOOL willReconnect = NO; 400 | 401 | if (reconnectMode > PTPusherAutoReconnectModeNoReconnect && _numberOfReconnectAttempts < _maximumNumberOfReconnectAttempts) { 402 | willReconnect = YES; 403 | } 404 | 405 | if ([self.delegate respondsToSelector:@selector(pusher:connection:didDisconnectWithError:willAttemptReconnect:)]) { 406 | [self.delegate pusher:self connection:connection didDisconnectWithError:error willAttemptReconnect:willReconnect]; 407 | } 408 | 409 | if (willReconnect) { 410 | [self reconnectUsingMode:reconnectMode]; 411 | } 412 | } 413 | 414 | #pragma mark - Private 415 | 416 | - (void)beginAuthorizationOperation:(PTPusherChannelAuthorizationOperation *)operation 417 | { 418 | [authorizationQueue addOperation:operation]; 419 | } 420 | 421 | - (void)reconnectUsingMode:(PTPusherAutoReconnectMode)reconnectMode 422 | { 423 | _numberOfReconnectAttempts++; 424 | 425 | NSTimeInterval delay; 426 | 427 | switch (reconnectMode) { 428 | case PTPusherAutoReconnectModeReconnectImmediately: 429 | delay = 0; 430 | break; 431 | case PTPusherAutoReconnectModeReconnectWithConfiguredDelay: 432 | delay = self.reconnectDelay; 433 | break; 434 | case PTPusherAutoReconnectModeReconnectWithBackoffDelay: 435 | delay = self.reconnectDelay * _numberOfReconnectAttempts; 436 | break; 437 | default: 438 | delay = 0; 439 | break; 440 | } 441 | 442 | if ([self.delegate respondsToSelector:@selector(pusher:connectionWillAutomaticallyReconnect:afterDelay:)]) { 443 | BOOL shouldProceed = [self.delegate pusher:self connectionWillAutomaticallyReconnect:_connection afterDelay:delay]; 444 | 445 | if (!shouldProceed) return; 446 | } 447 | 448 | dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delay * NSEC_PER_SEC); 449 | dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 450 | [_connection connect]; 451 | }); 452 | } 453 | 454 | @end 455 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTPusherAPI.h: -------------------------------------------------------------------------------- 1 | // 2 | // PTPusherAPI.h 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 14/08/2011. 6 | // Copyright 2011 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** A simple interface to the Pusher REST API. 12 | 13 | This functionality used to be part of the main PTPusher library but 14 | has been extracted into a standalone component. 15 | 16 | The PTPusher client has support for client-sent events but if your account does not 17 | support these you can use this class to send events using the standard Pusher REST API. 18 | 19 | As well as your Pusher API key, you will also need your app ID and secret key 20 | for signing requests. You should take care not to expose these in your application's 21 | header files. 22 | */ 23 | @interface PTPusherAPI : NSObject 24 | 25 | ///------------------------------------------------------------------------------------/ 26 | /// @name Initialisation 27 | ///------------------------------------------------------------------------------------/ 28 | 29 | /** Designated initializer 30 | 31 | You will need your account credentials which can be located on your account dashboard. 32 | 33 | @param aKey Your Pusher API key 34 | @param anAppID Your Pusher app ID 35 | @param aSecretKey Your Pusher app secret. 36 | */ 37 | - (id)initWithKey:(NSString *)aKey appID:(NSString *)anAppID secretKey:(NSString *)aSecretKey; 38 | 39 | ///------------------------------------------------------------------------------------/ 40 | /// @name Triggering events 41 | ///------------------------------------------------------------------------------------/ 42 | 43 | /** Triggers an event on the specified channel. 44 | 45 | The event data will be converted to JSON format so needs to be any object that can be 46 | transformed into JSON (typically any plist-compatible object). 47 | 48 | @param eventName The name of the event to trigger. 49 | @param channelName The channel the event should be triggered on. 50 | @param eventData The JSON-compatible data object for the event. 51 | */ 52 | - (void)triggerEvent:(NSString *)eventName onChannel:(NSString *)channelName data:(id)eventData socketID:(NSString *)socketID; 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTPusherAPI.m: -------------------------------------------------------------------------------- 1 | // 2 | // PTPusherAPI.m 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 14/08/2011. 6 | // Copyright 2011 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import "PTPusherAPI.h" 10 | #import "PTURLRequestOperation.h" 11 | #import "PTJSON.h" 12 | #import "NSString+Hashing.h" 13 | #import "NSDictionary+QueryString.h" 14 | 15 | 16 | #define kPUSHER_API_DEFAULT_HOST @"api.pusherapp.com" 17 | 18 | @implementation PTPusherAPI { 19 | NSString *key, *appID, *secretKey; 20 | NSOperationQueue *operationQueue; 21 | } 22 | 23 | - (id)initWithKey:(NSString *)aKey appID:(NSString *)anAppID secretKey:(NSString *)aSecretKey 24 | { 25 | if ((self = [super init])) { 26 | key = [aKey copy]; 27 | appID = [anAppID copy]; 28 | secretKey = [aSecretKey copy]; 29 | operationQueue = [[NSOperationQueue alloc] init]; 30 | } 31 | return self; 32 | } 33 | 34 | 35 | - (void)triggerEvent:(NSString *)eventName onChannel:(NSString *)channelName data:(id)eventData socketID:(NSString *)socketID 36 | { 37 | NSString *path = [NSString stringWithFormat:@"/apps/%@/channels/%@/events", appID, channelName]; 38 | NSData *bodyData = [[PTJSON JSONParser] JSONDataFromObject:eventData]; 39 | NSString *bodyString = [[NSString alloc] initWithData:bodyData encoding:NSUTF8StringEncoding]; 40 | 41 | NSMutableDictionary *queryParameters = [NSMutableDictionary dictionary]; 42 | 43 | queryParameters[@"body_md5"] = [[bodyString MD5Hash] lowercaseString]; 44 | queryParameters[@"auth_key"] = key; 45 | queryParameters[@"auth_timestamp"] = @([[NSDate date] timeIntervalSince1970]); 46 | queryParameters[@"auth_version"] = @"1.0"; 47 | queryParameters[@"name"] = eventName; 48 | 49 | if (socketID) { 50 | queryParameters[@"socket_id"] = socketID; 51 | } 52 | 53 | NSString *signatureString = [NSString stringWithFormat:@"POST\n%@\n%@", path, [queryParameters sortedQueryString]]; 54 | 55 | queryParameters[@"auth_signature"] = [signatureString HMACDigestUsingSecretKey:secretKey]; 56 | 57 | NSString *URLString = [NSString stringWithFormat:@"http://%@%@?%@", kPUSHER_API_DEFAULT_HOST, path, [queryParameters sortedQueryString]]; 58 | 59 | NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:URLString]]; 60 | [request setHTTPBody:bodyData]; 61 | [request setHTTPMethod:@"POST"]; 62 | [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; 63 | 64 | PTURLRequestOperation *operation = [[PTURLRequestOperation alloc] initWithURLRequest:request]; 65 | [operationQueue addOperation:operation]; 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTPusherChannel.h: -------------------------------------------------------------------------------- 1 | // 2 | // PTPusherClient.h 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 23/04/2010. 6 | // Copyright 2010 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "PTPusherEventPublisher.h" 11 | #import "PTEventListener.h" 12 | #import "PTPusherPresenceChannelDelegate.h" 13 | #import "PTPusherMacros.h" 14 | 15 | @class PTPusher; 16 | @class PTPusherEventDispatcher; 17 | 18 | /** A PTPusherChannel object represents a single Pusher channel. 19 | 20 | Channels can be used as a means of filtering or controlling access to events. 21 | 22 | Channels do not need to be explicitly created; they are created on demand. To obtain 23 | an instance of a PTPusherChannel, you need to subscribe to it first. 24 | 25 | You should not create PTPusherChannel instances directly as they require subscription and 26 | possibly authorization; you should instead use the subscribeTo methods provided by PTPusher. 27 | 28 | There are three types of channel: 29 | 30 | + Public channels can be subscribed to by anyone who knows their name. 31 | 32 | + Private channels allow you to control access to the data you are broadcasting. 33 | 34 | + Presence channels you to 'register' user information on subscription, and let other members of the channel know who's online. 35 | 36 | Channels can be subscribed to or unsubscribed to at any time, even before the initial 37 | Pusher connection has been established. 38 | 39 | Generally, channel objects will exist from the point of creation until you explicitly unsubscribe 40 | from them, unless you maintain your own strong references to the channel object. Channels become 41 | implicitly unsubscribed when the connection is lost but will be re-subscribed once connection 42 | is re-established. This means you can use the same channel object across connections. 43 | 44 | See the README for more information on channel object lifetime. 45 | */ 46 | @interface PTPusherChannel : NSObject 47 | 48 | ///------------------------------------------------------------------------------------/ 49 | /// @name Properties 50 | ///------------------------------------------------------------------------------------/ 51 | 52 | /** The channel name. 53 | */ 54 | @property (nonatomic, readonly) NSString *name; 55 | 56 | /** Indicates that this channel has been subscribed to. 57 | 58 | Whilst public channels are subscribed to immediately, presence and private channels require 59 | authorization first. This property will be set to YES once an internal Pusher event has 60 | been received indicating that the channel subscription has been registered. 61 | 62 | You can bind to events on a channel without waiting for it to become subscribed and any 63 | event bindings will be kept if the channel becomes unsubscribed due to a loss of connection. 64 | */ 65 | @property (nonatomic, readonly, getter=isSubscribed) BOOL subscribed; 66 | 67 | /** Indicates whether or not this is a private channel. 68 | */ 69 | @property (nonatomic, readonly) BOOL isPrivate; 70 | 71 | /** Indicates whether or not this is a presence channel. 72 | */ 73 | @property (nonatomic, readonly) BOOL isPresence; 74 | 75 | + (id)channelWithName:(NSString *)name pusher:(PTPusher *)pusher; 76 | - (id)initWithName:(NSString *)channelName pusher:(PTPusher *)pusher; 77 | - (void)authorizeWithCompletionHandler:(void(^)(BOOL, NSDictionary *, NSError *))completionHandler; 78 | 79 | ///------------------------------------------------------------------------------------/ 80 | /// @name Unsubscribing 81 | ///------------------------------------------------------------------------------------/ 82 | 83 | /** Unsubscribes from the channel. 84 | 85 | PTPusher will remove any strong references to the channel when you unsusbcribe. If you 86 | do not have any strong references to the channel object, it will be deallocated after 87 | unsubscribing. 88 | 89 | If there is an active connection when this is called, an unsubscribe event will be 90 | ssent to the server. 91 | */ 92 | - (void)unsubscribe; 93 | 94 | @end 95 | 96 | /** A PTPusherPrivateChannel object represents a private Pusher channel. 97 | 98 | Private channels should be used when access to the channel needs to be restricted in some way. 99 | In order for a user to subscribe to a private channel permission must be authorised. 100 | 101 | Private channel names always have the prefix of "private-". 102 | 103 | Only private and presence channels support client triggered events. 104 | */ 105 | @interface PTPusherPrivateChannel : PTPusherChannel 106 | 107 | ///------------------------------------------------------------------------------------/ 108 | /// @name Triggering events 109 | ///------------------------------------------------------------------------------------/ 110 | 111 | /** Triggers a named event directly over the connection. 112 | 113 | Client events have the following restrictions: 114 | 115 | + The user must be subscribed to the channel that the event is being triggered on. 116 | 117 | + Client events can only be triggered on private and presence channels because they require authentication. 118 | 119 | + Client events must be prefixed by client-. Events with any other prefix will be rejected by the Pusher server, as will events sent to channels to which the client is not subscribed. 120 | 121 | If you attempt to trigger event on a channel while isSubscribed is NO, the event will not be sent. 122 | 123 | If the event name does not have a prefix of "client-", it will be added automatically. 124 | 125 | The event data must be an object that can be serialized as JSON, typically an NSArray or NSDictionary although 126 | it could be a simple string. 127 | */ 128 | - (void)triggerEventNamed:(NSString *)eventName data:(id)eventData; 129 | 130 | @end 131 | 132 | @class PTPusherChannelMembers; 133 | 134 | /** A PTPusherPresenceChannel object represents a Pusher presence channel. 135 | 136 | Presence channels build on the security of Private channels and expose the additional feature 137 | of an awareness of who is subscribed to that channel. This makes it extremely easy to build 138 | chat room and "who's online" type functionality to your application. 139 | 140 | Presence channel names always have the prefix of "presence-". 141 | 142 | Unlike the Pusher Javascript client API, PTPusherPresenceChannel does not use events to notify 143 | when members are added or removed. Instead, you should assign a presenceDelegate which will 144 | be notified of these events. 145 | 146 | @see PTPusherPresenceChannelDelegate 147 | */ 148 | @interface PTPusherPresenceChannel : PTPusherPrivateChannel 149 | 150 | ///------------------------------------------------------------------------------------/ 151 | /// @name Properties 152 | ///------------------------------------------------------------------------------------/ 153 | 154 | /** The presence delegate for the receiver. 155 | 156 | The presence delegate will be notified of presence channel-specific events, such as the initial 157 | member list on subscription and member added/removed events. 158 | */ 159 | @property (nonatomic, weak) id presenceDelegate; 160 | 161 | /** Returns the channel member list. 162 | */ 163 | @property (nonatomic, readonly) PTPusherChannelMembers *members; 164 | 165 | @end 166 | 167 | /** Represents a single member in a presence channel. 168 | * 169 | * Object subscripting can be used to access individual keys in a user's info dictionary. 170 | * 171 | */ 172 | @interface PTPusherChannelMember : NSObject 173 | 174 | /** The user's ID. 175 | */ 176 | @property (nonatomic, readonly) NSString *userID; 177 | 178 | /** A dictionary of user info - this is normally application specific. 179 | * 180 | */ 181 | @property (nonatomic, readonly) NSDictionary *userInfo; 182 | 183 | /** Provides object subscripting access to userInfo data. 184 | */ 185 | - (id)objectForKeyedSubscript:(id )key; 186 | 187 | @end 188 | 189 | /** Represents an unordered collection of members in a presence channel. 190 | * 191 | * Individual members are represented by instances of the class PTPusherChannelMember. 192 | * 193 | * This object supports subscripting for member access (where the user ID is the key). 194 | * 195 | * If you require an ordered list of members (e.g. to display in a table view) 196 | * you should implement the presence delegate methods and maintain your own ordered list. 197 | * 198 | */ 199 | @interface PTPusherChannelMembers : NSObject 200 | 201 | /** The number of members in the channel. 202 | */ 203 | @property (nonatomic, readonly) NSInteger count; 204 | 205 | /** The ID of the client's member. 206 | */ 207 | @property (nonatomic, copy, readonly) NSString *myID; 208 | 209 | /** The client member. 210 | */ 211 | @property (nonatomic, readonly) PTPusherChannelMember *me; 212 | 213 | /** Can be used to look up a channel member by ID. 214 | 215 | @return The member with the given ID, or nil if it does not exist. 216 | */ 217 | - (PTPusherChannelMember *)memberWithID:(NSString *)userID; 218 | 219 | /** Can be used to iterate over each member in the channel. 220 | */ 221 | - (void)enumerateObjectsUsingBlock:(void (^)(id obj, BOOL *stop))block; 222 | 223 | /** Provides object subscripting access to members by key. 224 | 225 | @param key The member ID 226 | @returns The member with the specified ID, or nil if it does not exist. 227 | */ 228 | - (id)objectForKeyedSubscript:(id )key; 229 | 230 | @end 231 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTPusherChannel.m: -------------------------------------------------------------------------------- 1 | // 2 | // PTPusherClient.m 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 23/04/2010. 6 | // Copyright 2010 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import "PTPusherChannel.h" 10 | #import "PTPusher.h" 11 | #import "PTPusherEvent.h" 12 | #import "PTPusherEventDispatcher.h" 13 | #import "PTTargetActionEventListener.h" 14 | #import "PTBlockEventListener.h" 15 | #import "PTPusherChannelAuthorizationOperation.h" 16 | #import "PTPusherErrors.h" 17 | #import "PTJSON.h" 18 | 19 | @interface PTPusher () 20 | - (void)__unsubscribeFromChannel:(PTPusherChannel *)channel; 21 | - (void)beginAuthorizationOperation:(PTPusherChannelAuthorizationOperation *)operation; 22 | @end 23 | 24 | @interface PTPusherChannel () 25 | @property (nonatomic, weak) PTPusher *pusher; 26 | @property (nonatomic, strong) PTPusherEventDispatcher *dispatcher; 27 | @property (nonatomic, assign, readwrite) BOOL subscribed; 28 | @property (nonatomic, readonly) NSMutableArray *internalBindings; 29 | @end 30 | 31 | #pragma mark - 32 | 33 | @implementation PTPusherChannel 34 | 35 | + (id)channelWithName:(NSString *)name pusher:(PTPusher *)pusher 36 | { 37 | if ([name hasPrefix:@"private-"]) { 38 | return [[PTPusherPrivateChannel alloc] initWithName:name pusher:pusher]; 39 | } 40 | if ([name hasPrefix:@"presence-"]) { 41 | return [[PTPusherPresenceChannel alloc] initWithName:name pusher:pusher]; 42 | } 43 | return [[self alloc] initWithName:name pusher:pusher]; 44 | } 45 | 46 | - (id)initWithName:(NSString *)channelName pusher:(PTPusher *)aPusher 47 | { 48 | if (self = [super init]) { 49 | _name = [channelName copy]; 50 | _pusher = aPusher; 51 | _dispatcher = [[PTPusherEventDispatcher alloc] init]; 52 | _internalBindings = [[NSMutableArray alloc] init]; 53 | 54 | /* 55 | Set up event handlers for pre-defined channel events 56 | 57 | We *must* use block-based bindings with a weak reference to the channel. 58 | Using a target-action binding will create a retain cycle between the channel 59 | and the target/action binding object. 60 | */ 61 | __weak PTPusherChannel *weakChannel = self; 62 | 63 | [self.internalBindings addObject: 64 | [self bindToEventNamed:@"pusher_internal:subscription_succeeded" 65 | handleWithBlock:^(PTPusherEvent *event) { 66 | [weakChannel handleSubscribeEvent:event]; 67 | }]]; 68 | 69 | [self.internalBindings addObject: 70 | [self bindToEventNamed:@"subscription_error" 71 | handleWithBlock:^(PTPusherEvent *event) { 72 | [weakChannel handleSubcribeErrorEvent:event]; 73 | }]]; 74 | } 75 | return self; 76 | } 77 | 78 | - (void)dealloc 79 | { 80 | [self.internalBindings enumerateObjectsUsingBlock:^(id object, NSUInteger index, BOOL *stop) { 81 | [_dispatcher removeBinding:object]; 82 | }]; 83 | } 84 | 85 | - (BOOL)isPrivate 86 | { 87 | return NO; 88 | } 89 | 90 | - (BOOL)isPresence 91 | { 92 | return NO; 93 | } 94 | 95 | #pragma mark - Subscription events 96 | 97 | - (void)handleSubscribeEvent:(PTPusherEvent *)event 98 | { 99 | self.subscribed = YES; 100 | 101 | if ([self.pusher.delegate respondsToSelector:@selector(pusher:didSubscribeToChannel:)]) { 102 | [self.pusher.delegate pusher:self.pusher didSubscribeToChannel:self]; 103 | } 104 | } 105 | 106 | - (void)handleSubcribeErrorEvent:(PTPusherEvent *)event 107 | { 108 | if ([self.pusher.delegate respondsToSelector:@selector(pusher:didFailToSubscribeToChannel:withError:)]) { 109 | NSDictionary *userInfo = @{PTPusherErrorUnderlyingEventKey: event}; 110 | NSError *error = [NSError errorWithDomain:PTPusherErrorDomain code:PTPusherSubscriptionError userInfo:userInfo]; 111 | [self.pusher.delegate pusher:self.pusher didFailToSubscribeToChannel:self withError:error]; 112 | } 113 | } 114 | 115 | #pragma mark - Authorization 116 | 117 | - (void)authorizeWithCompletionHandler:(void(^)(BOOL, NSDictionary *, NSError *))completionHandler 118 | { 119 | completionHandler(YES, @{}, nil); // public channels do not require authorization 120 | } 121 | 122 | #pragma mark - Binding to events 123 | 124 | - (PTPusherEventBinding *)bindToEventNamed:(NSString *)eventName target:(id)target action:(SEL)selector 125 | { 126 | return [self.dispatcher addEventListenerForEventNamed:eventName target:target action:selector]; 127 | } 128 | 129 | - (PTPusherEventBinding *)bindToEventNamed:(NSString *)eventName handleWithBlock:(PTPusherEventBlockHandler)block 130 | { 131 | return [self bindToEventNamed:eventName handleWithBlock:block queue:dispatch_get_main_queue()]; 132 | } 133 | 134 | - (PTPusherEventBinding *)bindToEventNamed:(NSString *)eventName handleWithBlock:(PTPusherEventBlockHandler)block queue:(dispatch_queue_t)queue 135 | { 136 | return [self.dispatcher addEventListenerForEventNamed:eventName block:block queue:queue]; 137 | } 138 | 139 | - (void)removeBinding:(PTPusherEventBinding *)binding 140 | { 141 | [self.dispatcher removeBinding:binding]; 142 | } 143 | 144 | - (void)removeAllBindings 145 | { 146 | NSMutableArray *bindingsToRemove = [NSMutableArray array]; 147 | 148 | // need to unpack the bindings from the nested arrays, so we can 149 | // iterate over them safely whilst removing them from the dispatcher 150 | for (NSArray *bindingsArray in [self.dispatcher.bindings allValues]) { 151 | for (PTPusherEventBinding *binding in bindingsArray) { 152 | if (![self.internalBindings containsObject:binding]) { 153 | [bindingsToRemove addObject:binding]; 154 | } 155 | } 156 | } 157 | 158 | for (PTPusherEventBinding *binding in bindingsToRemove) { 159 | [self.dispatcher removeBinding:binding]; 160 | } 161 | } 162 | 163 | #pragma mark - Dispatching events 164 | 165 | - (void)dispatchEvent:(PTPusherEvent *)event 166 | { 167 | [self.dispatcher dispatchEvent:event]; 168 | 169 | [[NSNotificationCenter defaultCenter] 170 | postNotificationName:PTPusherEventReceivedNotification 171 | object:self 172 | userInfo:@{PTPusherEventUserInfoKey: event}]; 173 | } 174 | 175 | #pragma mark - Internal use only 176 | 177 | - (void)subscribeWithAuthorization:(NSDictionary *)authData 178 | { 179 | if (self.isSubscribed) return; 180 | 181 | [self.pusher sendEventNamed:@"pusher:subscribe" 182 | data:@{@"channel": self.name} 183 | channel:nil]; 184 | } 185 | 186 | - (void)unsubscribe 187 | { 188 | [self.pusher __unsubscribeFromChannel:self]; 189 | } 190 | 191 | - (void)handleDisconnect 192 | { 193 | self.subscribed = NO; 194 | } 195 | 196 | @end 197 | 198 | #pragma mark - 199 | 200 | @implementation PTPusherPrivateChannel { 201 | NSOperationQueue *_clientEventQueue; 202 | } 203 | 204 | - (id)initWithName:(NSString *)channelName pusher:(PTPusher *)aPusher 205 | { 206 | if ((self = [super initWithName:channelName pusher:aPusher])) { 207 | _clientEventQueue = [[NSOperationQueue alloc] init]; 208 | _clientEventQueue.maxConcurrentOperationCount = 1; 209 | _clientEventQueue.name = @"com.pusher.libPusher.clientEventQueue"; 210 | _clientEventQueue.suspended = YES; 211 | } 212 | return self; 213 | } 214 | 215 | - (void)handleSubscribeEvent:(PTPusherEvent *)event 216 | { 217 | [super handleSubscribeEvent:event]; 218 | [_clientEventQueue setSuspended:NO]; 219 | } 220 | 221 | - (void)handleDisconnect 222 | { 223 | [super handleDisconnect]; 224 | [_clientEventQueue setSuspended:YES]; 225 | } 226 | 227 | - (BOOL)isPrivate 228 | { 229 | return YES; 230 | } 231 | 232 | - (void)authorizeWithCompletionHandler:(void(^)(BOOL, NSDictionary *, NSError *))completionHandler 233 | { 234 | PTPusherChannelAuthorizationOperation *authOperation = [PTPusherChannelAuthorizationOperation operationWithAuthorizationURL:self.pusher.authorizationURL channelName:self.name socketID:self.pusher.connection.socketID]; 235 | 236 | [authOperation setCompletionHandler:^(PTPusherChannelAuthorizationOperation *operation) { 237 | completionHandler(operation.isAuthorized, operation.authorizationData, operation.error); 238 | }]; 239 | 240 | if ([self.pusher.delegate respondsToSelector:@selector(pusher:willAuthorizeChannel:withRequest:)]) { 241 | [self.pusher.delegate pusher:self.pusher willAuthorizeChannel:self withRequest:authOperation.mutableURLRequest]; 242 | } 243 | 244 | [self.pusher beginAuthorizationOperation:authOperation]; 245 | } 246 | 247 | - (void)subscribeWithAuthorization:(NSDictionary *)authData 248 | { 249 | if (self.isSubscribed) return; 250 | 251 | NSMutableDictionary *eventData = [authData mutableCopy]; 252 | eventData[@"channel"] = self.name; 253 | 254 | [self.pusher sendEventNamed:@"pusher:subscribe" 255 | data:eventData 256 | channel:nil]; 257 | } 258 | 259 | #pragma mark - Triggering events 260 | 261 | - (void)triggerEventNamed:(NSString *)eventName data:(id)eventData 262 | { 263 | if (![eventName hasPrefix:@"client-"]) { 264 | eventName = [@"client-" stringByAppendingString:eventName]; 265 | } 266 | 267 | __weak PTPusherChannel *weakSelf = self; 268 | 269 | [_clientEventQueue addOperationWithBlock:^{ 270 | [weakSelf.pusher sendEventNamed:eventName data:eventData channel:weakSelf.name]; 271 | }]; 272 | } 273 | 274 | @end 275 | 276 | #pragma mark - 277 | 278 | @interface PTPusherChannelMembers () 279 | 280 | @property (nonatomic, copy, readwrite) NSString *myID; 281 | 282 | - (void)reset; 283 | - (void)handleSubscription:(NSDictionary *)subscriptionData; 284 | - (PTPusherChannelMember *)handleMemberAdded:(NSDictionary *)memberData; 285 | - (PTPusherChannelMember *)handleMemberRemoved:(NSDictionary *)memberData; 286 | 287 | @end 288 | 289 | @implementation PTPusherPresenceChannel 290 | 291 | - (id)initWithName:(NSString *)channelName pusher:(PTPusher *)aPusher 292 | { 293 | if ((self = [super initWithName:channelName pusher:aPusher])) { 294 | _members = [[PTPusherChannelMembers alloc] init]; 295 | 296 | /* Set up event handlers for pre-defined channel events. 297 | As above, use blocks as proxies to a weak channel reference to avoid retain cycles. 298 | */ 299 | __weak PTPusherPresenceChannel *weakChannel = self; 300 | 301 | [self.internalBindings addObject: 302 | [self bindToEventNamed:@"pusher_internal:member_added" 303 | handleWithBlock:^(PTPusherEvent *event) { 304 | [weakChannel handleMemberAddedEvent:event]; 305 | }]]; 306 | 307 | [self.internalBindings addObject: 308 | [self bindToEventNamed:@"pusher_internal:member_removed" 309 | handleWithBlock:^(PTPusherEvent *event) { 310 | [weakChannel handleMemberRemovedEvent:event]; 311 | }]]; 312 | 313 | } 314 | return self; 315 | } 316 | 317 | - (void)handleDisconnect 318 | { 319 | [super handleDisconnect]; 320 | [self.members reset]; 321 | } 322 | 323 | - (void)subscribeWithAuthorization:(NSDictionary *)authData 324 | { 325 | [super subscribeWithAuthorization:authData]; 326 | 327 | NSDictionary *channelData = [[PTJSON JSONParser] objectFromJSONString:authData[@"channel_data"]]; 328 | self.members.myID = channelData[@"user_id"]; 329 | } 330 | 331 | - (void)handleSubscribeEvent:(PTPusherEvent *)event 332 | { 333 | [super handleSubscribeEvent:event]; 334 | [self.members handleSubscription:event.data]; 335 | [self.presenceDelegate presenceChannelDidSubscribe:self]; 336 | } 337 | 338 | - (BOOL)isPresence 339 | { 340 | return YES; 341 | } 342 | 343 | - (void)handleMemberAddedEvent:(PTPusherEvent *)event 344 | { 345 | PTPusherChannelMember *member = [self.members handleMemberAdded:event.data]; 346 | 347 | [self.presenceDelegate presenceChannel:self memberAdded:member]; 348 | } 349 | 350 | - (void)handleMemberRemovedEvent:(PTPusherEvent *)event 351 | { 352 | PTPusherChannelMember *member = [self.members handleMemberRemoved:event.data]; 353 | 354 | [self.presenceDelegate presenceChannel:self memberRemoved:member]; 355 | } 356 | 357 | @end 358 | 359 | #pragma mark - 360 | 361 | @implementation PTPusherChannelMember 362 | 363 | - (id)initWithUserID:(NSString *)userID userInfo:(NSDictionary *)userInfo 364 | { 365 | if ((self = [super init])) { 366 | _userID = [userID copy]; 367 | _userInfo = [userInfo copy]; 368 | } 369 | return self; 370 | } 371 | 372 | - (NSString *)description 373 | { 374 | return [NSString stringWithFormat:@"", self.userID, self.userInfo]; 375 | } 376 | 377 | - (id)objectForKeyedSubscript:(id )key 378 | { 379 | return self.userInfo[key]; 380 | } 381 | 382 | @end 383 | 384 | @implementation PTPusherChannelMembers { 385 | NSMutableDictionary *_members; 386 | } 387 | 388 | - (id)init 389 | { 390 | self = [super init]; 391 | if (self) { 392 | _members = [[NSMutableDictionary alloc] init]; 393 | } 394 | return self; 395 | } 396 | 397 | - (void)reset 398 | { 399 | _members = [[NSMutableDictionary alloc] init]; 400 | self.myID = nil; 401 | } 402 | 403 | - (NSString *)description 404 | { 405 | return [NSString stringWithFormat:@"", _members]; 406 | } 407 | 408 | - (NSInteger)count 409 | { 410 | return _members.count; 411 | } 412 | 413 | - (id)objectForKeyedSubscript:(id )key 414 | { 415 | return _members[key]; 416 | } 417 | 418 | - (void)enumerateObjectsUsingBlock:(void (^)(id obj, BOOL *stop))block 419 | { 420 | [_members enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { 421 | block(obj, stop); 422 | }]; 423 | } 424 | 425 | 426 | - (PTPusherChannelMember *)me 427 | { 428 | return self[self.myID]; 429 | } 430 | 431 | - (PTPusherChannelMember *)memberWithID:(NSString *)userID 432 | { 433 | return self[userID]; 434 | } 435 | 436 | #pragma mark - Channel event handling 437 | 438 | - (void)handleSubscription:(NSDictionary *)subscriptionData 439 | { 440 | NSDictionary *memberHash = subscriptionData[@"presence"][@"hash"]; 441 | 442 | [memberHash enumerateKeysAndObjectsUsingBlock:^(NSString *userID, NSDictionary *userInfo, BOOL *stop) { 443 | PTPusherChannelMember *member = [[PTPusherChannelMember alloc] initWithUserID:userID userInfo:userInfo]; 444 | _members[userID] = member; 445 | }]; 446 | } 447 | 448 | - (PTPusherChannelMember *)handleMemberAdded:(NSDictionary *)memberData 449 | { 450 | PTPusherChannelMember *member = [self memberWithID:memberData[@"user_id"]]; 451 | if (member == nil) { 452 | member = [[PTPusherChannelMember alloc] initWithUserID:memberData[@"user_id"] userInfo:memberData[@"user_info"]]; 453 | _members[member.userID] = member; 454 | } 455 | return member; 456 | } 457 | 458 | - (PTPusherChannelMember *)handleMemberRemoved:(NSDictionary *)memberData 459 | { 460 | PTPusherChannelMember *member = [self memberWithID:memberData[@"user_id"]]; 461 | if (member) { 462 | [_members removeObjectForKey:member.userID]; 463 | } 464 | return member; 465 | } 466 | 467 | @end 468 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTPusherChannelAuthorizationOperation.m: -------------------------------------------------------------------------------- 1 | // 2 | // PTPusherChannelAuthorizationOperation.m 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 14/08/2011. 6 | // Copyright 2011 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import "PTPusherChannelAuthorizationOperation.h" 10 | #import "NSDictionary+QueryString.h" 11 | #import "PTJSON.h" 12 | #import "PTPusher+Testing.h" 13 | 14 | @interface PTPusherChannelAuthorizationBypassOperation : NSOperation 15 | @property (nonatomic, readwrite) NSError *error; 16 | @end 17 | 18 | @interface PTPusherChannelAuthorizationOperation () 19 | @property (nonatomic, strong, readwrite) NSDictionary *authorizationData; 20 | @property (nonatomic, readwrite) NSError *error; 21 | @end 22 | 23 | @implementation PTPusherChannelAuthorizationOperation 24 | 25 | - (NSMutableURLRequest *)mutableURLRequest 26 | { 27 | // we can be sure this is always mutable 28 | return (NSMutableURLRequest *)URLRequest; 29 | } 30 | 31 | + (id)operationWithAuthorizationURL:(NSURL *)URL channelName:(NSString *)channelName socketID:(NSString *)socketID 32 | { 33 | NSAssert(URL, @"URL is required for authorization! (Did you set PTPusher.authorizationURL?)"); 34 | 35 | // a short-circuit for testing, using a special URL 36 | if ([[URL absoluteString] isEqualToString:PTPusherAuthorizationBypassURL]) { 37 | return [[PTPusherChannelAuthorizationBypassOperation alloc] init]; 38 | } 39 | 40 | NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL]; 41 | [request setHTTPMethod:@"POST"]; 42 | [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; 43 | 44 | NSMutableDictionary *requestData = [NSMutableDictionary dictionary]; 45 | requestData[@"socket_id"] = socketID; 46 | requestData[@"channel_name"] = channelName; 47 | 48 | [request setHTTPBody:[[requestData sortedQueryString] dataUsingEncoding:NSUTF8StringEncoding]]; 49 | 50 | return [[self alloc] initWithURLRequest:request]; 51 | } 52 | 53 | - (void)finish 54 | { 55 | if (self.isCancelled) { 56 | [super finish]; 57 | return; 58 | } 59 | 60 | if (self.connectionError) { 61 | self.error = [NSError errorWithDomain:PTPusherErrorDomain code:PTPusherChannelAuthorizationConnectionError userInfo:@{NSUnderlyingErrorKey: self.connectionError}]; 62 | } 63 | else { 64 | _authorized = YES; 65 | 66 | if ([URLResponse isKindOfClass:[NSHTTPURLResponse class]]) { 67 | _authorized = ([(NSHTTPURLResponse *)URLResponse statusCode] == 200 || [(NSHTTPURLResponse *)URLResponse statusCode] == 201); 68 | } 69 | 70 | if (_authorized) { 71 | _authorizationData = [[PTJSON JSONParser] objectFromJSONData:responseData]; 72 | 73 | if (![_authorizationData isKindOfClass:[NSDictionary class]]) { 74 | NSDictionary *userInfo = nil; 75 | 76 | if (_authorizationData) { // make sure it isn't nil as a result of invalid JSON first 77 | userInfo = @{@"reason": @"Authorization data was not a dictionary", @"authorization_data": _authorizationData}; 78 | } 79 | else { 80 | userInfo = @{@"reason": @"Authorization data was not valid JSON"}; 81 | } 82 | 83 | self.error = [NSError errorWithDomain:PTPusherErrorDomain code:PTPusherChannelAuthorizationBadResponseError userInfo:userInfo]; 84 | 85 | _authorized = NO; 86 | } 87 | } 88 | } 89 | 90 | if (self.completionHandler) { 91 | self.completionHandler(self); 92 | } 93 | 94 | [super finish]; 95 | } 96 | 97 | @end 98 | 99 | @implementation PTPusherChannelAuthorizationBypassOperation { 100 | void (^_completionHandler)(id); 101 | } 102 | 103 | @synthesize error; 104 | 105 | - (void)setCompletionHandler:(void (^)(id))completionHandler 106 | { 107 | _completionHandler = completionHandler; 108 | } 109 | 110 | - (void)main 111 | { 112 | // we complete after a tiny delay, to simulate the asynchronous nature 113 | // of channel authorization. The low priorty queue ensures any polling 114 | // in the test (which probably use the main queue/thread is not broken. 115 | 116 | double delayInSeconds = 0.1; 117 | dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 118 | dispatch_after(popTime, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^(void){ 119 | _completionHandler(self); 120 | }); 121 | } 122 | 123 | - (BOOL)isAuthorized 124 | { 125 | return YES; 126 | } 127 | 128 | - (NSDictionary *)authorizationData 129 | { 130 | return @{}; 131 | } 132 | 133 | - (NSMutableURLRequest *)mutableURLRequest 134 | { 135 | return [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:PTPusherAuthorizationBypassURL]]; 136 | } 137 | 138 | - (NSError *)connectionError 139 | { 140 | return nil; 141 | } 142 | 143 | @end 144 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTPusherConnection.h: -------------------------------------------------------------------------------- 1 | // 2 | // PTPusherConnection.h 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 13/08/2011. 6 | // Copyright 2011 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "PTPusherMacros.h" 11 | 12 | @class PTPusherConnection; 13 | @class PTPusherEvent; 14 | 15 | @protocol PTPusherConnectionDelegate 16 | - (BOOL)pusherConnectionWillConnect:(PTPusherConnection *)connection; 17 | - (void)pusherConnectionDidConnect:(PTPusherConnection *)connection; 18 | - (void)pusherConnection:(PTPusherConnection *)connection didDisconnectWithCode:(NSInteger)errorCode reason:(NSString *)reason wasClean:(BOOL)wasClean; 19 | - (void)pusherConnection:(PTPusherConnection *)connection didFailWithError:(NSError *)error wasConnected:(BOOL)wasConnected; 20 | - (void)pusherConnection:(PTPusherConnection *)connection didReceiveEvent:(PTPusherEvent *)event; 21 | @end 22 | 23 | extern NSString *const PTPusherConnectionEstablishedEvent; 24 | extern NSString *const PTPusherConnectionPingEvent; 25 | 26 | typedef enum { 27 | PTPusherConnectionDisconnecting = 0, 28 | PTPusherConnectionDisconnected, 29 | PTPusherConnectionConnecting, 30 | PTPusherConnectionAwaitingHandshake, 31 | PTPusherConnectionConnected 32 | } PTPusherConnectionState; 33 | 34 | @interface PTPusherConnection : NSObject 35 | 36 | @property (nonatomic, weak) id delegate; 37 | 38 | /** Indicates if the connection is connected to the Pusher service. 39 | 40 | @return YES, if the socket has connected and a handshake has been received from the server, otherwise NO. 41 | */ 42 | @property (nonatomic, readonly, getter=isConnected) BOOL connected; 43 | 44 | /** The unique socket ID for this connection. 45 | 46 | Every time the connection connects to the service, a new socket ID is received on handshake. 47 | 48 | This is normally used when authorizing private and presence channel subscriptions. 49 | */ 50 | @property (nonatomic, copy, readonly) NSString *socketID; 51 | 52 | /** The Pusher service URL. 53 | */ 54 | @property (nonatomic, readonly) NSURL *URL; 55 | 56 | /* If the connection does not receive any new data within the time specified, 57 | a ping event will be sent. 58 | 59 | Defaults to 120s as recommended by the Pusher protocol documentation. You should not 60 | normally need to change this. 61 | */ 62 | @property (nonatomic, assign) NSTimeInterval activityTimeout; 63 | 64 | /* The amount of time to wait for a pong in response to a ping before disconnecting. 65 | 66 | Defaults to 30s as recommended by the Pusher protocol documentation. You should not 67 | normally need to change this. 68 | */ 69 | @property (nonatomic, assign) NSTimeInterval pongTimeout; 70 | 71 | ///------------------------------------------------------------------------------------/ 72 | /// @name Initialisation 73 | ///------------------------------------------------------------------------------------/ 74 | 75 | /** Creates a new PTPusherConnection instance. 76 | 77 | Connections are not opened immediately; an explicit call to connect is required. 78 | 79 | @param aURL The websocket endpoint 80 | @param delegate The delegate for this connection 81 | */ 82 | - (id)initWithURL:(NSURL *)aURL; 83 | 84 | ///------------------------------------------------------------------------------------/ 85 | /// @name Managing connections 86 | ///------------------------------------------------------------------------------------/ 87 | 88 | /** Establishes a web socket connection to the Pusher server. 89 | 90 | The delegate will only be sent a didConnect message when the web socket receives a 91 | 'connection_established' event from Pusher, regardless of the web socket's connection state. 92 | 93 | Calling this does nothing if already connected. 94 | */ 95 | - (void)connect; 96 | 97 | /** Closes the web socket connection 98 | 99 | Calling this does nothing if already disconnected. 100 | */ 101 | - (void)disconnect; 102 | 103 | ///------------------------------------------------------------------------------------/ 104 | /// @name Sending data 105 | ///------------------------------------------------------------------------------------/ 106 | 107 | /** Sends an object over the web socket connection. 108 | 109 | The object will be serialized to JSON before sending, so the object must be anything 110 | that can be converted into JSON (typically, any plist compatible object). 111 | */ 112 | - (void)send:(id)object; 113 | 114 | @end 115 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTPusherConnection.m: -------------------------------------------------------------------------------- 1 | // 2 | // PTPusherConnection.m 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 13/08/2011. 6 | // Copyright 2011 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import "PTPusherConnection.h" 10 | #import "PTPusherEvent.h" 11 | #define SR_ENABLE_LOG 12 | #import "SRWebSocket.h" 13 | #import "PTJSON.h" 14 | 15 | NSString *const PTPusherConnectionEstablishedEvent = @"pusher:connection_established"; 16 | NSString *const PTPusherConnectionPingEvent = @"pusher:ping"; 17 | NSString *const PTPusherConnectionPongEvent = @"pusher:pong"; 18 | 19 | @interface PTPusherConnection () 20 | @property (nonatomic, copy) NSString *socketID; 21 | @property (nonatomic, assign) PTPusherConnectionState state; 22 | @property (nonatomic, strong) NSTimer *pingTimer; 23 | @property (nonatomic, strong) NSTimer *pongTimer; 24 | @end 25 | 26 | @implementation PTPusherConnection { 27 | SRWebSocket *socket; 28 | NSURLRequest *request; 29 | } 30 | 31 | - (id)initWithURL:(NSURL *)aURL 32 | { 33 | if ((self = [super init])) { 34 | request = [NSURLRequest requestWithURL:aURL]; 35 | 36 | #ifdef DEBUG 37 | NSLog(@"[pusher] Debug logging enabled"); 38 | #endif 39 | 40 | // Timeout defaults as recommended by the Pusher protocol documentation. 41 | self.activityTimeout = 120.0; 42 | self.pongTimeout = 30.0; 43 | } 44 | return self; 45 | } 46 | 47 | - (void)dealloc 48 | { 49 | [self.pingTimer invalidate]; 50 | [self.pongTimer invalidate]; 51 | [socket setDelegate:nil]; 52 | [socket close]; 53 | } 54 | 55 | - (BOOL)isConnected 56 | { 57 | return (self.state == PTPusherConnectionConnected); 58 | } 59 | 60 | - (NSURL *)URL 61 | { 62 | return request.URL; 63 | } 64 | 65 | #pragma mark - Connection management 66 | 67 | - (void)connect; 68 | { 69 | if (self.state >= PTPusherConnectionConnecting) return; 70 | 71 | BOOL shouldConnect = [self.delegate pusherConnectionWillConnect:self]; 72 | 73 | if (!shouldConnect) return; 74 | 75 | socket = [[SRWebSocket alloc] initWithURLRequest:request]; 76 | socket.delegate = self; 77 | 78 | [socket open]; 79 | 80 | self.state = PTPusherConnectionConnecting; 81 | } 82 | 83 | - (void)disconnect; 84 | { 85 | if (self.state <= PTPusherConnectionDisconnected) return; 86 | 87 | [socket close]; 88 | 89 | self.state = PTPusherConnectionDisconnecting; 90 | } 91 | 92 | #pragma mark - Sending data 93 | 94 | - (void)send:(id)object 95 | { 96 | if (self.isConnected == NO) return; 97 | 98 | NSData *JSONData = [[PTJSON JSONParser] JSONDataFromObject:object]; 99 | NSString *message = [[NSString alloc] initWithData:JSONData encoding:NSUTF8StringEncoding]; 100 | [socket send:message]; 101 | } 102 | 103 | #pragma mark - SRWebSocket delegate methods 104 | 105 | - (void)webSocketDidOpen:(SRWebSocket *)webSocket 106 | { 107 | self.state = PTPusherConnectionAwaitingHandshake; 108 | } 109 | 110 | - (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error; 111 | { 112 | [self.pingTimer invalidate]; 113 | [self.pongTimer invalidate]; 114 | 115 | BOOL wasConnected = self.isConnected; 116 | self.state = PTPusherConnectionDisconnected; 117 | self.socketID = nil; 118 | socket = nil; 119 | 120 | // we always call this last, to prevent a race condition if the delegate calls 'connect' 121 | [self.delegate pusherConnection:self didFailWithError:error wasConnected:wasConnected]; 122 | } 123 | 124 | - (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean 125 | { 126 | [self.pingTimer invalidate]; 127 | [self.pongTimer invalidate]; 128 | 129 | self.state = PTPusherConnectionDisconnected; 130 | self.socketID = nil; 131 | socket = nil; 132 | 133 | // we always call this last, to prevent a race condition if the delegate calls 'connect' 134 | [self.delegate pusherConnection:self didDisconnectWithCode:(NSInteger)code reason:(NSString *)reason wasClean:wasClean]; 135 | } 136 | 137 | - (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(NSString *)message 138 | { 139 | [self resetPingPongTimer]; 140 | 141 | NSDictionary *messageDictionary = [[PTJSON JSONParser] objectFromJSONString:message]; 142 | PTPusherEvent *event = [PTPusherEvent eventFromMessageDictionary:messageDictionary]; 143 | 144 | if ([event.name isEqualToString:PTPusherConnectionPongEvent]) { 145 | #ifdef DEBUG 146 | NSLog(@"[pusher] Server responded to ping (pong!)"); 147 | #endif 148 | return; 149 | } 150 | 151 | if ([event.name isEqualToString:PTPusherConnectionEstablishedEvent]) { 152 | self.socketID = (event.data)[@"socket_id"]; 153 | self.state = PTPusherConnectionConnected; 154 | 155 | [self.delegate pusherConnectionDidConnect:self]; 156 | } 157 | 158 | [self.delegate pusherConnection:self didReceiveEvent:event]; 159 | } 160 | 161 | #pragma mark - Ping/Pong/Activity Timeouts 162 | 163 | - (void)sendPing 164 | { 165 | [self send:@{@"event": @"pusher:ping"}]; 166 | } 167 | 168 | - (void)resetPingPongTimer 169 | { 170 | [self.pingTimer invalidate]; 171 | // Any activity also invalidates the pong timer if set 172 | [self.pongTimer invalidate]; 173 | 174 | self.pingTimer = [NSTimer scheduledTimerWithTimeInterval:self.activityTimeout target:self selector:@selector(handleActivityTimeout) userInfo:nil repeats:NO]; 175 | } 176 | 177 | - (void)handleActivityTimeout 178 | { 179 | #ifdef DEBUG 180 | NSLog(@"[pusher] Pusher connection activity timeout reached, sending ping to server"); 181 | #endif 182 | 183 | [self sendPing]; 184 | 185 | self.pongTimer = [NSTimer scheduledTimerWithTimeInterval:self.pongTimeout target:self selector:@selector(handlePongTimeout) userInfo:nil repeats:NO]; 186 | } 187 | 188 | - (void)handlePongTimeout 189 | { 190 | #ifdef DEBUG 191 | NSLog(@"[pusher] Server did not respond to ping within timeout, disconnecting"); 192 | #endif 193 | 194 | [self disconnect]; 195 | } 196 | 197 | @end 198 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTPusherDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // PTPusherDelegate.h 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 22/03/2010. 6 | // Copyright 2010 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import "PTPusherMacros.h" 10 | 11 | @class PTPusher; 12 | @class PTPusherConnection; 13 | @class PTPusherChannel; 14 | @class PTPusherEvent; 15 | @class PTPusherErrorEvent; 16 | 17 | /** Implementing the PTPusherDelegate protocol lets you react to important events in the Pusher client's 18 | lifetime, such as connection and disconnection, channel subscription and errors. 19 | 20 | All of the delegate methods are optional; you only need to implement what is required for your app. 21 | 22 | It may be useful to assign a delegate to monitor the status of the connection; you could use this to update 23 | your user interface accordingly. 24 | */ 25 | @protocol PTPusherDelegate 26 | 27 | @optional 28 | 29 | ///------------------------------------------------------------------------------------/ 30 | /// @name Connection handling 31 | ///------------------------------------------------------------------------------------/ 32 | 33 | /** Notifies the delegate that the PTPusher instance is about to connect to the Pusher service. 34 | 35 | @param pusher The PTPusher instance that is connecting. 36 | @param connection The connection for the pusher instance. 37 | @return NO to abort the connection attempt. 38 | */ 39 | - (BOOL)pusher:(PTPusher *)pusher connectionWillConnect:(PTPusherConnection *)connection; 40 | 41 | /** Notifies the delegate that the PTPusher instance has connected to the Pusher service successfully. 42 | 43 | @param pusher The PTPusher instance that has connected. 44 | @param connection The connection for the pusher instance. 45 | */ 46 | - (void)pusher:(PTPusher *)pusher connectionDidConnect:(PTPusherConnection *)connection; 47 | 48 | /** Notifies the delegate that the PTPusher instance has disconnected from the Pusher service. 49 | 50 | Clients should check the value of the willAttemptReconnect parameter before trying to reconnect manually. 51 | In most cases, the client will try and automatically reconnect, depending on the error code returned by 52 | the Pusher service. 53 | 54 | If willAttemptReconnect is YES, clients can expect a pusher:connectionWillReconnect:afterDelay: message 55 | immediately following this one. Clients can return NO from that delegate method to cancel the automatic 56 | reconnection attempt. 57 | 58 | If the client has disconnected due to a fatal Pusher error (as indicated by the error code), 59 | willAttemptReconnect will be NO and the error domain will be `PTPusherFatalErrorDomain`. 60 | 61 | @param pusher The PTPusher instance that has connected. 62 | @param connection The connection for the pusher instance. 63 | @param error If the connection disconnected abnormally, error will be non-nil. 64 | @param willAttemptReconnect YES if the client will try and reconnect automatically. 65 | */ 66 | - (void)pusher:(PTPusher *)pusher connection:(PTPusherConnection *)connection didDisconnectWithError:(NSError *)error willAttemptReconnect:(BOOL)willAttemptReconnect; 67 | 68 | /** Notifies the delegate that the PTPusher instance failed to connect to the Pusher service. 69 | 70 | In the case of connection failures, the client will *not* attempt to reconnect automatically. 71 | Instead, clients should implement this method and check the error code and manually reconnect 72 | the client if it makes sense to do so. 73 | 74 | @param pusher The PTPusher instance that has connected. 75 | @param connection The connection for the pusher instance. 76 | @param error The connection error. 77 | */ 78 | - (void)pusher:(PTPusher *)pusher connection:(PTPusherConnection *)connection failedWithError:(NSError *)error; 79 | 80 | /** Notifies the delegate that the PTPusher instance will attempt to automatically reconnect. 81 | 82 | You may wish to use this method to keep track of the number of automatic reconnection attempts and abort after a fixed number. 83 | 84 | @param pusher The PTPusher instance that has connected. 85 | @param connection The connection for the pusher instance. 86 | @return NO if you do not want the client to attempt an automatic reconnection. 87 | */ 88 | - (BOOL)pusher:(PTPusher *)pusher connectionWillAutomaticallyReconnect:(PTPusherConnection *)connection afterDelay:(NSTimeInterval)delay; 89 | 90 | ///------------------------------------------------------------------------------------/ 91 | /// @name Channel subscription and authorization 92 | ///------------------------------------------------------------------------------------/ 93 | 94 | /** Notifies the delegate of the request that will be used to authorize access to a channel. 95 | 96 | When using the Pusher Javascript client, authorization typically relies on an existing session cookie 97 | on the server; when the Javascript client makes an AJAX POST to the server, the server can return 98 | the user's credentials based on their current session. 99 | 100 | When using libPusher, there will likely be no existing server-side session; authorization will 101 | need to happen by some other means (e.g. an authorization token or HTTP basic auth). 102 | 103 | By implementing this delegate method, you will be able to set any credentials as necessary by 104 | modifying the request as required (such as setting POST parameters or headers). 105 | 106 | @param pusher The PTPusher instance that is requesting authorization 107 | @param channel The channel that requires authorizing 108 | @param request A mutable URL request that will be POSTed to the configured `authorizationURL` 109 | */ 110 | - (void)pusher:(PTPusher *)pusher willAuthorizeChannel:(PTPusherChannel *)channel withRequest:(NSMutableURLRequest *)request; 111 | 112 | /** Allows the delegate to return authorization data in the format required by Pusher from a 113 | non-standard respnse. 114 | 115 | When using a remote server to authorize access to a private channel, the server is expected to 116 | return an authorization payload in a specific format which is then sent to Pusher when connecting 117 | to a private channel. 118 | 119 | Sometimes, a server might return a non-standard response, for example, the auth data may be a sub-set 120 | of some bigger response. 121 | 122 | If implemented, Pusher will call this method with the response data returned from the authorization 123 | URL and will use whatever dictionary is returned instead. 124 | */ 125 | - (NSDictionary *)pusher:(PTPusher *)pusher authorizationPayloadFromResponseData:(NSDictionary *)responseData; 126 | 127 | /** Notifies the delegate that the PTPusher instance has subscribed to the specified channel. 128 | 129 | This method will be called after any channel authorization has taken place and when a subscribe event has been received. 130 | 131 | @param pusher The PTPusher instance that has connected. 132 | @param channel The channel that was subscribed to. 133 | */ 134 | - (void)pusher:(PTPusher *)pusher didSubscribeToChannel:(PTPusherChannel *)channel; 135 | 136 | /** Notifies the delegate that the PTPusher instance has unsubscribed from the specified channel. 137 | 138 | This method will be called immediately after unsubscribing from a channel. 139 | 140 | @param pusher The PTPusher instance that has connected. 141 | @param channel The channel that was unsubscribed from. 142 | */ 143 | - (void)pusher:(PTPusher *)pusher didUnsubscribeFromChannel:(PTPusherChannel *)channel; 144 | 145 | /** Notifies the delegate that the PTPusher instance failed to subscribe to the specified channel. 146 | 147 | The most common reason for subscribing failing is authorization failing for private/presence channels. 148 | 149 | @param pusher The PTPusher instance that has connected. 150 | @param channel The channel that was subscribed to. 151 | @param error The error returned when attempting to subscribe. 152 | */ 153 | - (void)pusher:(PTPusher *)pusher didFailToSubscribeToChannel:(PTPusherChannel *)channel withError:(NSError *)error; 154 | 155 | ///------------------------------------------------------------------------------------/ 156 | /// @name Errors 157 | ///------------------------------------------------------------------------------------/ 158 | 159 | /** Notifies the delegate that an error event has been received. 160 | 161 | If a client is binding to all events, either through the client or using NSNotificationCentre, they will also 162 | receive notification of this event like any other. 163 | 164 | @param pusher The PTPusher instance that received the event. 165 | @param errorEvent The error event. 166 | */ 167 | - (void)pusher:(PTPusher *)pusher didReceiveErrorEvent:(PTPusherErrorEvent *)errorEvent; 168 | 169 | @end 170 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTPusherErrors.h: -------------------------------------------------------------------------------- 1 | // 2 | // PTPusherErrors.h 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 14/08/2011. 6 | // Copyright 2011 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | enum { 12 | PTPusherSubscriptionError = 0, 13 | PTPusherSubscriptionUnknownAuthorisationError 14 | }; 15 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTPusherEvent.h: -------------------------------------------------------------------------------- 1 | // 2 | // PTPusherEvent.h 3 | // PusherEvents 4 | // 5 | // Created by Luke Redpath on 22/03/2010. 6 | // Copyright 2010 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | extern NSString *const PTPusherDataKey; 12 | extern NSString *const PTPusherEventKey; 13 | extern NSString *const PTPusherChannelKey; 14 | 15 | /** A value object representing a Pusher event. 16 | 17 | All events dispatched by libPusher (via either bindings or notifications) will be represented 18 | by instances of this class. 19 | */ 20 | @interface PTPusherEvent : NSObject 21 | 22 | ///------------------------------------------------------------------------------------/ 23 | /// @name Properties 24 | ///------------------------------------------------------------------------------------/ 25 | 26 | /** The event name. 27 | */ 28 | @property (nonatomic, readonly) NSString *name; 29 | 30 | /** The channel that this event originated from. 31 | */ 32 | @property (strong, nonatomic, readonly) NSString *channel; 33 | 34 | /** The event data. 35 | 36 | Event data will typically be any kind of object that can be represented as JSON, often 37 | an NSArray or NSDictionary but can be a simple string. 38 | */ 39 | @property (strong, nonatomic, readonly) id data; 40 | 41 | /** The time the event was received. 42 | */ 43 | @property (nonatomic, readonly, strong) NSDate *timeReceived; 44 | 45 | - (id)initWithEventName:(NSString *)name channel:(NSString *)channel data:(id)data; 46 | + (id)eventFromMessageDictionary:(NSDictionary *)dictionary; 47 | 48 | @end 49 | 50 | typedef enum { 51 | PTPusherErrorUnknown = -1, 52 | PTPusherErrorSSLRequired = 4000, 53 | PTPusherErrorApplicationUnknown = 4001, 54 | PTPusherErrorApplicationDisabled = 4002 55 | } PTPusherServerErrorCodes; 56 | 57 | /** A special sub-class of Pusher event, representing pusher:error events. 58 | 59 | This will be yielded to the Pusher client delegate as well as through the normal event 60 | dispatch mechanism. 61 | 62 | This class adds some convenient properties for accessing error details. 63 | */ 64 | @interface PTPusherErrorEvent : PTPusherEvent 65 | 66 | /** A textual description of the error. 67 | */ 68 | @property (weak, nonatomic, readonly) NSString *message; 69 | 70 | /** The error code. See PTPusherServerErrorCodes for available errors. 71 | */ 72 | @property (nonatomic, readonly) NSInteger code; 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTPusherEvent.m: -------------------------------------------------------------------------------- 1 | // 2 | // PTPusherEvent.m 3 | // PusherEvents 4 | // 5 | // Created by Luke Redpath on 22/03/2010. 6 | // Copyright 2010 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import "PTPusherEvent.h" 10 | #import "PTJSON.h" 11 | 12 | NSString *const PTPusherDataKey = @"data"; 13 | NSString *const PTPusherEventKey = @"event"; 14 | NSString *const PTPusherChannelKey = @"channel"; 15 | 16 | @implementation PTPusherEvent 17 | 18 | + (id)eventFromMessageDictionary:(NSDictionary *)dictionary 19 | { 20 | if ([dictionary[PTPusherEventKey] isEqualToString:@"pusher:error"]) { 21 | return [[PTPusherErrorEvent alloc] initWithEventName:dictionary[PTPusherEventKey] channel:nil data:dictionary[PTPusherDataKey]]; 22 | } 23 | return [[self alloc] initWithEventName:dictionary[PTPusherEventKey] channel:dictionary[PTPusherChannelKey] data:dictionary[PTPusherDataKey]]; 24 | } 25 | 26 | - (id)initWithEventName:(NSString *)name channel:(NSString *)channel data:(id)data 27 | { 28 | if (self = [super init]) { 29 | _name = [name copy]; 30 | _channel = [channel copy]; 31 | _timeReceived = [NSDate date]; 32 | 33 | // try and deserialize the data as JSON if possible 34 | if ([data respondsToSelector:@selector(dataUsingEncoding:)]) { 35 | _data = [[[PTJSON JSONParser] objectFromJSONString:data] copy]; 36 | 37 | if (_data == nil) { 38 | NSLog(@"[pusher] Error parsing event data (not JSON?)"); 39 | _data = [data copy]; 40 | } 41 | } 42 | else { 43 | _data = [data copy]; 44 | } 45 | } 46 | return self; 47 | } 48 | 49 | 50 | - (NSString *)description 51 | { 52 | return [NSString stringWithFormat:@"", self.channel, self.name, self.data]; 53 | } 54 | 55 | @end 56 | 57 | #pragma mark - 58 | 59 | @implementation PTPusherErrorEvent 60 | 61 | - (NSString *)message 62 | { 63 | return (self.data)[@"message"]; 64 | } 65 | 66 | - (NSInteger)code 67 | { 68 | id eventCode = (self.data)[@"code"]; 69 | 70 | if (eventCode == nil || eventCode == [NSNull null]) { 71 | return PTPusherErrorUnknown; 72 | } 73 | return [eventCode integerValue]; 74 | } 75 | 76 | - (NSString *)description 77 | { 78 | return [NSString stringWithFormat:@"", (long)self.code, self.message]; 79 | } 80 | 81 | @end 82 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTPusherEventDispatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // PTPusherEventDispatcher.h 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 13/08/2011. 6 | // Copyright 2011 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "PTEventListener.h" 11 | 12 | @class PTPusherEventBinding; 13 | 14 | @interface PTPusherEventDispatcher : NSObject 15 | 16 | @property (nonatomic, readonly) NSDictionary *bindings; 17 | 18 | - (PTPusherEventBinding *)addEventListener:(id)listener forEventNamed:(NSString *)eventName; 19 | - (void)removeBinding:(PTPusherEventBinding *)binding; 20 | - (void)removeAllBindings; 21 | @end 22 | 23 | /** Represents an event binding created when calling one of the binding methods defined 24 | in the PTPusherEventBindings protocol. 25 | 26 | You should keep a reference to binding objects if you need to remove them later. 27 | 28 | For more information on managing event bindings, see the README. 29 | */ 30 | @interface PTPusherEventBinding : NSObject 31 | 32 | /** The event name this binding is bound to. 33 | */ 34 | @property (nonatomic, readonly) NSString *eventName; 35 | 36 | /** Returns YES if this binding is still attached to its event publisher. 37 | 38 | Retained references to bindings can become invalid as a result of another object 39 | calling removeBinding: with this binding or removeAllBindings. 40 | 41 | You can safely discard invalid binding instances. 42 | */ 43 | @property (nonatomic, readonly, getter=isValid) BOOL valid; 44 | 45 | - (id)initWithEventListener:(id)eventListener eventName:(NSString *)eventName; 46 | @end 47 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTPusherEventDispatcher.m: -------------------------------------------------------------------------------- 1 | // 2 | // PTPusherEventDispatcher.m 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 13/08/2011. 6 | // Copyright 2011 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import "PTPusherEventDispatcher.h" 10 | #import "PTPusherEvent.h" 11 | 12 | @interface PTPusherEventBinding () 13 | - (void)invalidate; 14 | @end 15 | 16 | @implementation PTPusherEventDispatcher { 17 | NSMutableDictionary *_bindings; 18 | } 19 | 20 | - (id)init 21 | { 22 | if ((self = [super init])) { 23 | _bindings = [[NSMutableDictionary alloc] init]; 24 | } 25 | return self; 26 | } 27 | 28 | #pragma mark - Managing event listeners 29 | 30 | - (PTPusherEventBinding *)addEventListener:(id)listener forEventNamed:(NSString *)eventName 31 | { 32 | NSMutableArray *bindingsForEvent = _bindings[eventName]; 33 | 34 | if (bindingsForEvent == nil) { 35 | bindingsForEvent = [NSMutableArray array]; 36 | _bindings[eventName] = bindingsForEvent; 37 | } 38 | PTPusherEventBinding *binding = [[PTPusherEventBinding alloc] initWithEventListener:listener eventName:eventName]; 39 | [bindingsForEvent addObject:binding]; 40 | 41 | return binding; 42 | } 43 | 44 | - (void)removeBinding:(PTPusherEventBinding *)binding 45 | { 46 | NSMutableArray *bindingsForEvent = _bindings[binding.eventName]; 47 | 48 | if ([bindingsForEvent containsObject:binding]) { 49 | [binding invalidate]; 50 | [bindingsForEvent removeObject:binding]; 51 | } 52 | } 53 | 54 | - (void)removeAllBindings 55 | { 56 | for (NSArray *eventBindings in [_bindings allValues]) { 57 | for (PTPusherEventBinding *binding in eventBindings) { 58 | [binding invalidate]; 59 | } 60 | } 61 | [_bindings removeAllObjects]; 62 | } 63 | 64 | #pragma mark - Dispatching events 65 | 66 | - (void)dispatchEvent:(PTPusherEvent *)event 67 | { 68 | for (PTPusherEventBinding *binding in _bindings[event.name]) { 69 | [binding dispatchEvent:event]; 70 | } 71 | } 72 | 73 | @end 74 | 75 | @implementation PTPusherEventBinding { 76 | id _eventListener; 77 | } 78 | 79 | - (id)initWithEventListener:(id)eventListener eventName:(NSString *)eventName 80 | { 81 | if ((self = [super init])) { 82 | _eventName = [eventName copy]; 83 | _eventListener = eventListener; 84 | } 85 | return self; 86 | } 87 | 88 | - (void)invalidate 89 | { 90 | if ([_eventListener respondsToSelector:@selector(invalidate)]) { 91 | [_eventListener invalidate]; 92 | } 93 | } 94 | 95 | - (void)dispatchEvent:(PTPusherEvent *)event 96 | { 97 | [_eventListener dispatchEvent:event]; 98 | } 99 | 100 | @end 101 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTPusherEventPublisher.h: -------------------------------------------------------------------------------- 1 | // 2 | // PTPusherEventPublisher.h 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 13/08/2011. 6 | // Copyright 2011 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class PTPusherEvent; 12 | @class PTPusherEventBinding; 13 | 14 | typedef void (^PTPusherEventBlockHandler) (PTPusherEvent *); 15 | 16 | /** Describes an object that provides events that can be bound to. 17 | 18 | Events in Pusher form the basis of all communication with the service. They are 19 | named messages that can carry arbitrary user data. All events in libPusher are 20 | represented by the class `PTPusherEvent`. 21 | 22 | An object that implements this protocol allows for binding to events. There are 23 | currently two classes that implement this protocol: `PTPusher` and `PTPusherChannel`. 24 | 25 | There are two primary binding mechanisms: target/action based and block-based. Which 26 | one you use depends entirely on the requirements of your application. 27 | */ 28 | @protocol PTPusherEventBindings 29 | 30 | /** Binds to the named event using the target/action mechanism. 31 | 32 | When the named event is received, the specified selector will be called on target, passing 33 | the `PTPusherEvent` as the only argument. 34 | 35 | The following code snippet sets up a binding for the event "new-message" on any channel: 36 | 37 | [pusher bindToEventNamed:@"new-message" target:self action:@selector(handleNewMessageEvent:)]; 38 | 39 | Then the event is triggered, the event will be dispatched to the target/action pair: 40 | 41 | - (void)handleNewMessageEvent:(PTPusherEvent *)event 42 | { 43 | // do something with event 44 | } 45 | */ 46 | - (PTPusherEventBinding *)bindToEventNamed:(NSString *)eventName target:(id)target action:(SEL)selector; 47 | 48 | /** Binds to the named event using a block callback. 49 | 50 | When the event is received, the block will be called with the `PTPusherEvent` as the only block argument. 51 | 52 | The following code snippet sets up a binding for the event "new-message" on any channel and handles that 53 | event when it is triggered: 54 | 55 | [pusher bindToEventNamed:@"new-message" handleWithBlock:^(PTPusherEvent *event) { 56 | // do something with event 57 | }]; 58 | 59 | The callback blocks will be dispatched asynchronously using Grand Central Dispatch on the main queue. 60 | */ 61 | - (PTPusherEventBinding *)bindToEventNamed:(NSString *)eventName handleWithBlock:(PTPusherEventBlockHandler)block; 62 | 63 | /** Binds to the named event using a block callback. 64 | 65 | Works the same as bindToEventNamed:handleWithBlock: but dispatches the callback block on the specified 66 | Grand Central Dispatch queue. 67 | 68 | You can use this method if you wish to handle events in a background or custom priority queue. 69 | */ 70 | - (PTPusherEventBinding *)bindToEventNamed:(NSString *)eventName handleWithBlock:(PTPusherEventBlockHandler)block queue:(dispatch_queue_t)queue; 71 | 72 | /** Removes the specified binding. 73 | 74 | Any further events will not trigger any callbacks after the binding has been removed. 75 | */ 76 | - (void)removeBinding:(PTPusherEventBinding *)binding; 77 | 78 | /** Removes all bindings that have been set up. 79 | 80 | Any retained references to PTPusherEventBinding objects will become invalid. 81 | */ 82 | - (void)removeAllBindings; 83 | 84 | @end 85 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTPusherMacros.h: -------------------------------------------------------------------------------- 1 | // 2 | // PTPusherMacros.h 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 10/02/2012. 6 | // Copyright (c) 2012 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #ifndef libPusher_PTPusherMacros_h 10 | #define libPusher_PTPusherMacros_h 11 | 12 | #define __PUSHER_DEPRECATED__ __attribute__((deprecated)) 13 | 14 | #define PT_DEFINE_SHARED_INSTANCE_USING_BLOCK(block) \ 15 | static dispatch_once_t pred = 0; \ 16 | __strong static id _sharedObject = nil; \ 17 | dispatch_once(&pred, ^{ \ 18 | _sharedObject = block(); \ 19 | }); \ 20 | return _sharedObject; \ 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTPusherMockConnection.h: -------------------------------------------------------------------------------- 1 | // 2 | // PTPusherMockConnection.h 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 11/05/2012. 6 | // Copyright (c) 2012 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "PTPusherConnection.h" 11 | 12 | #define kPTPusherSimulatedDisconnectionErrorCode 1001 13 | 14 | @interface PTPusherMockConnection : PTPusherConnection 15 | 16 | @property (nonatomic, readonly) NSArray *sentClientEvents; 17 | 18 | - (void)simulateServerEventNamed:(NSString *)name data:(id)data channel:(NSString *)channelName; 19 | - (void)simulateServerEventNamed:(NSString *)name data:(id)data; 20 | - (void)simulateUnexpectedDisconnection; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTPusherMockConnection.m: -------------------------------------------------------------------------------- 1 | // 2 | // PTPusherMockConnection.m 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 11/05/2012. 6 | // Copyright (c) 2012 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import "PTPusherMockConnection.h" 10 | #import "PTJSON.h" 11 | #import "PTPusherEvent.h" 12 | #import "SRWebSocket.h" 13 | 14 | @interface PTPusherConnection () 15 | @end 16 | 17 | @implementation PTPusherMockConnection { 18 | NSMutableArray *sentClientEvents; 19 | } 20 | 21 | @synthesize sentClientEvents; 22 | 23 | - (id)init 24 | { 25 | if ((self = [super initWithURL:nil])) { 26 | sentClientEvents = [[NSMutableArray alloc] init]; 27 | } 28 | return self; 29 | } 30 | 31 | - (void)connect 32 | { 33 | [self webSocketDidOpen:nil]; 34 | 35 | NSInteger socketID = (NSInteger)[NSDate timeIntervalSinceReferenceDate]; 36 | 37 | [self simulateServerEventNamed:PTPusherConnectionEstablishedEvent 38 | data:@{@"socket_id": @(socketID)}]; 39 | } 40 | 41 | - (void)disconnect 42 | { 43 | [self webSocket:nil didCloseWithCode:0 reason:nil wasClean:YES]; 44 | } 45 | 46 | - (void)send:(id)object 47 | { 48 | [self handleClientEvent:object]; 49 | } 50 | 51 | #pragma mark - Event simulation 52 | 53 | - (void)simulateServerEventNamed:(NSString *)name data:(id)data 54 | { 55 | [self simulateServerEventNamed:name data:data channel:nil]; 56 | } 57 | 58 | - (void)simulateServerEventNamed:(NSString *)name data:(id)data channel:(NSString *)channelName 59 | { 60 | NSMutableDictionary *event = [NSMutableDictionary dictionary]; 61 | 62 | event[PTPusherEventKey] = name; 63 | 64 | if (data) { 65 | event[PTPusherDataKey] = data; 66 | } 67 | 68 | if (channelName) { 69 | event[PTPusherChannelKey] = channelName; 70 | } 71 | 72 | NSString *message = [[PTJSON JSONParser] JSONStringFromObject:event]; 73 | 74 | [self webSocket:nil didReceiveMessage:message]; 75 | } 76 | 77 | - (void)simulateUnexpectedDisconnection 78 | { 79 | [self webSocket:nil didCloseWithCode:kPTPusherSimulatedDisconnectionErrorCode reason:nil wasClean:NO]; 80 | } 81 | 82 | #pragma mark - Client event handling 83 | 84 | - (void)handleClientEvent:(NSDictionary *)eventData 85 | { 86 | PTPusherEvent *event = [PTPusherEvent eventFromMessageDictionary:eventData]; 87 | 88 | [sentClientEvents addObject:event]; 89 | 90 | if ([event.name isEqualToString:@"pusher:subscribe"]) { 91 | [self handleSubscribeEvent:event]; 92 | } 93 | } 94 | 95 | - (void)handleSubscribeEvent:(PTPusherEvent *)subscribeEvent 96 | { 97 | [self simulateServerEventNamed:@"pusher_internal:subscription_succeeded" 98 | data:nil 99 | channel:(subscribeEvent.data)[PTPusherChannelKey]]; 100 | } 101 | 102 | @end 103 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTPusherPresenceChannelDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // PTPusherPresenceChannelDelegate.h 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 14/08/2011. 6 | // Copyright 2011 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "PTPusherMacros.h" 11 | 12 | @class PTPusherChannelMember; 13 | @class PTPusherPresenceChannel; 14 | 15 | @protocol PTPusherPresenceChannelDelegate 16 | 17 | /** Notifies the delegate that the presence channel subscribed successfully. 18 | 19 | Whenever you subscribe to a presence channel, a list of current subscribers will be returned by Pusher. 20 | 21 | The members list can be accessed using the `members` property on the channel. 22 | 23 | @param channel The presence channel that was subscribed to. 24 | */ 25 | - (void)presenceChannelDidSubscribe:(PTPusherPresenceChannel *)channel; 26 | 27 | /** Notifies the delegate that a member has joined the channel. 28 | 29 | @param channel The presence channel that was subscribed to. 30 | @param member The member that was removed. 31 | */ 32 | 33 | - (void)presenceChannel:(PTPusherPresenceChannel *)channel memberAdded:(PTPusherChannelMember *)member; 34 | 35 | /** Notifies the delegate that a member has left from the channel. 36 | 37 | @param channel The presence channel that was subscribed to. 38 | @param member The member that was removed. 39 | */ 40 | - (void)presenceChannel:(PTPusherPresenceChannel *)channel memberRemoved:(PTPusherChannelMember *)member; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTTargetActionEventListener.m: -------------------------------------------------------------------------------- 1 | // 2 | // PTTargetActionEventListener.m 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 14/08/2011. 6 | // Copyright 2011 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import "PTTargetActionEventListener.h" 10 | 11 | @interface PTTargetActionEventListener : NSObject 12 | @end 13 | 14 | @implementation PTTargetActionEventListener { 15 | id _target; 16 | SEL _action; 17 | BOOL _invalid; 18 | } 19 | 20 | - (id)initWithTarget:(id)aTarget action:(SEL)aSelector 21 | { 22 | if (self = [super init]) { 23 | _target = aTarget; 24 | _action = aSelector; 25 | _invalid = NO; 26 | } 27 | return self; 28 | } 29 | 30 | - (void)invalidate 31 | { 32 | _invalid = YES; 33 | } 34 | 35 | - (NSString *)description; 36 | { 37 | return [NSString stringWithFormat:@"", _target, NSStringFromSelector(_action)]; 38 | } 39 | 40 | - (void)dispatchEvent:(PTPusherEvent *)event; 41 | { 42 | #pragma clang diagnostic push 43 | #pragma clang diagnostic ignored "-Warc-performSelector-leaks" 44 | if (!_invalid) { 45 | [_target performSelector:_action withObject:event]; 46 | } 47 | #pragma clang diagnostic pop 48 | } 49 | 50 | @end 51 | 52 | @implementation PTPusherEventDispatcher (PTTargetActionFactory) 53 | 54 | - (PTPusherEventBinding *)addEventListenerForEventNamed:(NSString *)eventName target:(id)target action:(SEL)action 55 | { 56 | PTTargetActionEventListener *listener = [[PTTargetActionEventListener alloc] initWithTarget:target action:action]; 57 | return [self addEventListener:listener forEventNamed:eventName]; 58 | } 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/PTURLRequestOperation.m: -------------------------------------------------------------------------------- 1 | // 2 | // LRURLConnectionOperation.m 3 | // LRResty 4 | // 5 | // Created by Luke Redpath on 04/10/2010. 6 | // Copyright 2010 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import "PTURLRequestOperation.h" 10 | 11 | @interface PTURLRequestOperation () 12 | @property (nonatomic, strong, readwrite) NSURLResponse *URLResponse; 13 | @property (nonatomic, strong, readwrite) NSError *connectionError; 14 | @property (nonatomic, strong, readwrite) NSData *responseData; 15 | 16 | - (void)setExecuting:(BOOL)isExecuting; 17 | - (void)setFinished:(BOOL)isFinished; 18 | @end 19 | 20 | #pragma mark - 21 | 22 | @implementation PTURLRequestOperation 23 | 24 | @synthesize URLRequest; 25 | @synthesize URLResponse; 26 | @synthesize connectionError; 27 | @synthesize responseData; 28 | 29 | - (id)initWithURLRequest:(NSURLRequest *)request; 30 | { 31 | if ((self = [super init])) { 32 | URLRequest = request; 33 | } 34 | return self; 35 | } 36 | 37 | 38 | - (void)start 39 | { 40 | NSAssert(URLRequest, @"Cannot start URLRequestOperation without a NSURLRequest."); 41 | 42 | if (![NSThread isMainThread]) { 43 | return [self performSelector:@selector(start) onThread:[NSThread mainThread] withObject:nil waitUntilDone:NO]; 44 | } 45 | 46 | if ([self isCancelled]) { 47 | [self finish]; 48 | return; 49 | } 50 | 51 | [self setExecuting:YES]; 52 | 53 | URLConnection = [[NSURLConnection alloc] initWithRequest:URLRequest delegate:self startImmediately:NO]; 54 | 55 | if (URLConnection == nil) { 56 | [self setFinished:YES]; 57 | } 58 | 59 | // Common modes instead of default so it won't stall uiscrollview scrolling 60 | [URLConnection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; 61 | [URLConnection start]; 62 | } 63 | 64 | - (void)finish; 65 | { 66 | [self setFinished:YES]; 67 | } 68 | 69 | - (BOOL)isConcurrent 70 | { 71 | return YES; 72 | } 73 | 74 | - (BOOL)isExecuting 75 | { 76 | return _isExecuting; 77 | } 78 | 79 | - (BOOL)isFinished 80 | { 81 | return _isFinished; 82 | } 83 | 84 | #pragma mark - 85 | #pragma mark NSURLConnection delegate methods 86 | 87 | - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)theResponse 88 | { 89 | self.URLResponse = theResponse; 90 | self.responseData = [NSMutableData data]; 91 | 92 | [self checkForCancellation]; 93 | } 94 | 95 | - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 96 | { 97 | if (self.responseData == nil) { // this might be called before didReceiveResponse 98 | self.responseData = [NSMutableData data]; 99 | } 100 | 101 | [responseData appendData:data]; 102 | 103 | [self checkForCancellation]; 104 | } 105 | 106 | - (void)connectionDidFinishLoading:(NSURLConnection *)connection 107 | { 108 | [self finish]; 109 | } 110 | 111 | - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 112 | { 113 | self.connectionError = error; 114 | [self finish]; 115 | } 116 | 117 | - (void)cancelImmediately 118 | { 119 | [URLConnection cancel]; 120 | [self finish]; 121 | } 122 | 123 | - (void)checkForCancellation 124 | { 125 | if ([self isCancelled]) { 126 | [self cancelImmediately]; 127 | } 128 | } 129 | 130 | #pragma mark - 131 | #pragma mark Private methods 132 | 133 | - (void)setExecuting:(BOOL)isExecuting; 134 | { 135 | [self willChangeValueForKey:@"isExecuting"]; 136 | _isExecuting = isExecuting; 137 | [self didChangeValueForKey:@"isExecuting"]; 138 | } 139 | 140 | - (void)setFinished:(BOOL)isFinished; 141 | { 142 | [self willChangeValueForKey:@"isFinished"]; 143 | [self setExecuting:NO]; 144 | _isFinished = isFinished; 145 | [self didChangeValueForKey:@"isFinished"]; 146 | } 147 | 148 | @end 149 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/Private Headers/NSDictionary+QueryString.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+QueryString.h 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 23/04/2010. 6 | // Copyright 2010 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface NSDictionary (QueryString) 13 | 14 | - (NSString *)sortedQueryString; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/Private Headers/NSString+Hashing.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface NSString (Hashing) 4 | - (NSString *)MD5Hash; 5 | - (NSString *)HMACDigestUsingSecretKey:(id)secretKey; 6 | @end 7 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/Private Headers/PTBlockEventListener.h: -------------------------------------------------------------------------------- 1 | // 2 | // PTBlockEventListener.h 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 14/08/2011. 6 | // Copyright 2011 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "PTEventListener.h" 11 | #import "PTPusherEventDispatcher.h" 12 | 13 | typedef void (^PTBlockEventListenerBlock)(PTPusherEvent *); 14 | 15 | @interface PTPusherEventDispatcher (PTBlockEventFactory) 16 | 17 | - (PTPusherEventBinding *)addEventListenerForEventNamed:(NSString *)eventName 18 | block:(PTBlockEventListenerBlock)block 19 | queue:(dispatch_queue_t)queue; 20 | 21 | @end 22 | 23 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/Private Headers/PTJSON.h: -------------------------------------------------------------------------------- 1 | // 2 | // PTJSON.h 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 30/03/2012. 6 | // Copyright (c) 2012 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol PTJSONParser 12 | 13 | - (NSData *)JSONDataFromObject:(id)object; 14 | - (NSString *)JSONStringFromObject:(id)object; 15 | - (id)objectFromJSONData:(NSData *)data; 16 | - (id)objectFromJSONString:(NSString *)string; 17 | 18 | @end 19 | 20 | @interface PTJSON : NSObject 21 | 22 | /** 23 | Returns a JSON parser appropriate for the current platform. 24 | 25 | As of libPusher 1.5, the lowest supported deployment target is iOS 5.0 26 | so this will always return a parser that uses NSJSONSerialisation. 27 | */ 28 | + (id)JSONParser; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/Private Headers/PTPusherChannelAuthorizationOperation.h: -------------------------------------------------------------------------------- 1 | // 2 | // PTPusherChannelAuthorizationOperation.h 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 14/08/2011. 6 | // Copyright 2011 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "PTURLRequestOperation.h" 11 | 12 | typedef enum { 13 | PTPusherChannelAuthorizationConnectionError = 100, 14 | PTPusherChannelAuthorizationBadResponseError 15 | } PTPusherChannelAuthorizationError; 16 | 17 | @interface PTPusherChannelAuthorizationOperation : PTURLRequestOperation 18 | 19 | @property (nonatomic, copy) void (^completionHandler)(PTPusherChannelAuthorizationOperation *); 20 | @property (nonatomic, readonly, getter=isAuthorized) BOOL authorized; 21 | @property (nonatomic, strong, readonly) NSDictionary *authorizationData; 22 | @property (weak, nonatomic, readonly) NSMutableURLRequest *mutableURLRequest; 23 | @property (nonatomic, readonly) NSError *error; 24 | 25 | + (id)operationWithAuthorizationURL:(NSURL *)URL channelName:(NSString *)channelName socketID:(NSString *)socketID; 26 | @end 27 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/Private Headers/PTPusherChannel_Private.h: -------------------------------------------------------------------------------- 1 | // 2 | // PTPusherChannel_Private.h 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 25/11/2013. 6 | // 7 | // 8 | 9 | /** 10 | * These methods are for internal use only. 11 | */ 12 | @interface PTPusherChannel () 13 | - (void)subscribeWithAuthorization:(NSDictionary *)authData; 14 | - (void)unsubscribe; 15 | - (void)handleDisconnect; 16 | @end 17 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/Private Headers/PTTargetActionEventListener.h: -------------------------------------------------------------------------------- 1 | // 2 | // PTTargetActionEventListener.h 3 | // libPusher 4 | // 5 | // Created by Luke Redpath on 14/08/2011. 6 | // Copyright 2011 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "PTEventListener.h" 11 | #import "PTPusherEventDispatcher.h" 12 | 13 | @interface PTPusherEventDispatcher (PTTargetActionFactory) 14 | - (PTPusherEventBinding *)addEventListenerForEventNamed:(NSString *)eventName target:(id)target action:(SEL)action; 15 | @end 16 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/Private Headers/PTURLRequestOperation.h: -------------------------------------------------------------------------------- 1 | // 2 | // LRURLConnectionOperation.h 3 | // LRResty 4 | // 5 | // Created by Luke Redpath on 04/10/2010. 6 | // Copyright 2010 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface PTURLRequestOperation : NSOperation { 13 | BOOL _isExecuting; 14 | BOOL _isFinished; 15 | NSURLRequest *URLRequest; 16 | NSURLResponse *URLResponse; 17 | NSURLConnection *URLConnection; 18 | NSError *connectionError; 19 | NSMutableData *responseData; 20 | } 21 | @property (nonatomic, strong) NSURLRequest *URLRequest; 22 | @property (nonatomic, strong, readonly) NSURLResponse *URLResponse; 23 | @property (nonatomic, strong, readonly) NSError *connectionError; 24 | @property (nonatomic, strong, readonly) NSData *responseData; 25 | 26 | - (id)initWithURLRequest:(NSURLRequest *)request; 27 | - (void)finish; 28 | - (void)cancelImmediately; 29 | - (void)checkForCancellation; 30 | @end 31 | 32 | @interface PTURLRequestOperation (NSURLConnectionDelegate) 33 | - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)theResponse; 34 | - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data; 35 | - (void)connectionDidFinishLoading:(NSURLConnection *)connection; 36 | - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error; 37 | @end 38 | -------------------------------------------------------------------------------- /Pods/libPusher/Library/Pusher.h: -------------------------------------------------------------------------------- 1 | // 2 | // libPusher.h 3 | // Pods 4 | // 5 | // Created by Alexander Schuch on 08/04/13. 6 | // 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | #import 13 | #import 14 | -------------------------------------------------------------------------------- /Pods/libPusher/README-DIST.txt: -------------------------------------------------------------------------------- 1 | =============================================================================== 2 | README: libPusher distribution build 3 | =============================================================================== 4 | 5 | This package contains three static libraries: 6 | 7 | * libPusher-iphoneosXXa 8 | * libPusher-iphonesimulatorXX.a 9 | * libPusher-combined.a 10 | 11 | Where XX is the version of the SDK that the library was compiled with. 12 | 13 | It also contains a number of public headers that you will need in order to use the library in your project. 14 | 15 | The iphoneos library is compiled for armv7 devices and the iphonesimulator library is compiled for the simulator. You may use these if you wish to link to them separately for different targets in your project. 16 | 17 | Most people will want to use the combined library, which is a fat static library that will run on both the simulator and the device. 18 | 19 | =============================================================================== 20 | Installation 21 | =============================================================================== 22 | 23 | These instructions use the combined library: 24 | 25 | 1. Copy the libPusher-combined.a library in to your project. 26 | 27 | 2. In your target settings, under the Build Phases tab, expand "Link Binary With Libraries" and check that libPusher-combined.a appears there. If it does not, click the "+" symbol and add it. This links your target with the static library. 28 | 29 | 3. In your target build settings, locate the "Other Linker Flags" setting and add "-all_load". 30 | 31 | 4. Drag the contents of the headers directory into your project. 32 | 33 | 5. Link with the following libraries/frameworks: 34 | 35 | * libicucore.dylib 36 | * CFNetwork.framework 37 | * Security.framework 38 | * SystemConfiguration.framework 39 | 40 | 6. You should now be able to #import "PTPusher.h" and compile. 41 | 42 | =============================================================================== 43 | Notes 44 | =============================================================================== 45 | 46 | If you are upgrading, libPusher no longer uses the JSONKit library and the static library no longer contains a compiled version of JSONKit.m. 47 | 48 | By default, libPusher now uses NSJSONSerialization which is available on iOS 5.0 or OSX 10.7 and later. If you require support for older platforms, libPusher still has support for JSONKit as a fallback option, but you are required to link JSONKit to your app separately. 49 | 50 | For more information, see: 51 | https://github.com/lukeredpath/libPusher/wiki/Adding-libPusher-to-your-project 52 | 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PusherClient 2 | 3 | A react-native implementation of the Obj-C [libPusher](https://github.com/lukeredpath/libPusher) Pusher client library. 4 | 5 | ## TODO 6 | 7 | - [ ] Documentation 8 | - [ ] Add private channel support 9 | - [ ] Add presence channel support 10 | - [ ] Add support for triggering events (via `channel.trigger(eventName, payloadData)`) 11 | 12 | ## Installation 13 | 14 | *Coming soon.* 15 | 16 | ## Usage 17 | 18 | *Coming soon.* 19 | -------------------------------------------------------------------------------- /RNPusherClient.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 37AB3E5A1BA71D9100E08DFD /* RNPusherClient.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 37AB3E591BA71D9100E08DFD /* RNPusherClient.h */; }; 11 | 37AB3E5C1BA71D9100E08DFD /* RNPusherClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 37AB3E5B1BA71D9100E08DFD /* RNPusherClient.m */; }; 12 | 37AB3E621BA71D9100E08DFD /* libRNPusherClient.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 37AB3E561BA71D9100E08DFD /* libRNPusherClient.a */; }; 13 | BAA71A6F703EBA4D1C5F1D94 /* libPods-RNPusherClient.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FFEF5216A43057972AB5A432 /* libPods-RNPusherClient.a */; }; 14 | /* End PBXBuildFile section */ 15 | 16 | /* Begin PBXContainerItemProxy section */ 17 | 37AB3E631BA71D9100E08DFD /* PBXContainerItemProxy */ = { 18 | isa = PBXContainerItemProxy; 19 | containerPortal = 37AB3E4E1BA71D9100E08DFD /* Project object */; 20 | proxyType = 1; 21 | remoteGlobalIDString = 37AB3E551BA71D9100E08DFD; 22 | remoteInfo = RNPusherClient; 23 | }; 24 | /* End PBXContainerItemProxy section */ 25 | 26 | /* Begin PBXCopyFilesBuildPhase section */ 27 | 37AB3E541BA71D9100E08DFD /* CopyFiles */ = { 28 | isa = PBXCopyFilesBuildPhase; 29 | buildActionMask = 2147483647; 30 | dstPath = "include/$(PRODUCT_NAME)"; 31 | dstSubfolderSpec = 16; 32 | files = ( 33 | 37AB3E5A1BA71D9100E08DFD /* RNPusherClient.h in CopyFiles */, 34 | ); 35 | runOnlyForDeploymentPostprocessing = 0; 36 | }; 37 | /* End PBXCopyFilesBuildPhase section */ 38 | 39 | /* Begin PBXFileReference section */ 40 | 37AB3E561BA71D9100E08DFD /* libRNPusherClient.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNPusherClient.a; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | 37AB3E591BA71D9100E08DFD /* RNPusherClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNPusherClient.h; sourceTree = ""; }; 42 | 37AB3E5B1BA71D9100E08DFD /* RNPusherClient.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNPusherClient.m; sourceTree = ""; }; 43 | 37AB3E611BA71D9100E08DFD /* RNPusherClientTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RNPusherClientTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | 37AB3E671BA71D9100E08DFD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 45 | 61C228DC3C922571DD4AEB69 /* Pods-RNPusherClient.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNPusherClient.release.xcconfig"; path = "Pods/Target Support Files/Pods-RNPusherClient/Pods-RNPusherClient.release.xcconfig"; sourceTree = ""; }; 46 | C17A75306941DEAD3DF224C8 /* Pods-RNPusherClient.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNPusherClient.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RNPusherClient/Pods-RNPusherClient.debug.xcconfig"; sourceTree = ""; }; 47 | FFEF5216A43057972AB5A432 /* libPods-RNPusherClient.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNPusherClient.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 48 | /* End PBXFileReference section */ 49 | 50 | /* Begin PBXFrameworksBuildPhase section */ 51 | 37AB3E531BA71D9100E08DFD /* Frameworks */ = { 52 | isa = PBXFrameworksBuildPhase; 53 | buildActionMask = 2147483647; 54 | files = ( 55 | BAA71A6F703EBA4D1C5F1D94 /* libPods-RNPusherClient.a in Frameworks */, 56 | ); 57 | runOnlyForDeploymentPostprocessing = 0; 58 | }; 59 | 37AB3E5E1BA71D9100E08DFD /* Frameworks */ = { 60 | isa = PBXFrameworksBuildPhase; 61 | buildActionMask = 2147483647; 62 | files = ( 63 | 37AB3E621BA71D9100E08DFD /* libRNPusherClient.a in Frameworks */, 64 | ); 65 | runOnlyForDeploymentPostprocessing = 0; 66 | }; 67 | /* End PBXFrameworksBuildPhase section */ 68 | 69 | /* Begin PBXGroup section */ 70 | 0A615A5FEAED3D407852A404 /* Pods */ = { 71 | isa = PBXGroup; 72 | children = ( 73 | C17A75306941DEAD3DF224C8 /* Pods-RNPusherClient.debug.xcconfig */, 74 | 61C228DC3C922571DD4AEB69 /* Pods-RNPusherClient.release.xcconfig */, 75 | ); 76 | name = Pods; 77 | sourceTree = ""; 78 | }; 79 | 37AB3E4D1BA71D9100E08DFD = { 80 | isa = PBXGroup; 81 | children = ( 82 | 37AB3E581BA71D9100E08DFD /* RNPusherClient */, 83 | 37AB3E651BA71D9100E08DFD /* RNPusherClientTests */, 84 | 37AB3E571BA71D9100E08DFD /* Products */, 85 | 0A615A5FEAED3D407852A404 /* Pods */, 86 | F2993F4144FC861DCA6F1AE0 /* Frameworks */, 87 | ); 88 | sourceTree = ""; 89 | }; 90 | 37AB3E571BA71D9100E08DFD /* Products */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | 37AB3E561BA71D9100E08DFD /* libRNPusherClient.a */, 94 | 37AB3E611BA71D9100E08DFD /* RNPusherClientTests.xctest */, 95 | ); 96 | name = Products; 97 | sourceTree = ""; 98 | }; 99 | 37AB3E581BA71D9100E08DFD /* RNPusherClient */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 37AB3E591BA71D9100E08DFD /* RNPusherClient.h */, 103 | 37AB3E5B1BA71D9100E08DFD /* RNPusherClient.m */, 104 | ); 105 | path = RNPusherClient; 106 | sourceTree = ""; 107 | }; 108 | 37AB3E651BA71D9100E08DFD /* RNPusherClientTests */ = { 109 | isa = PBXGroup; 110 | children = ( 111 | 37AB3E661BA71D9100E08DFD /* Supporting Files */, 112 | ); 113 | path = RNPusherClientTests; 114 | sourceTree = ""; 115 | }; 116 | 37AB3E661BA71D9100E08DFD /* Supporting Files */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | 37AB3E671BA71D9100E08DFD /* Info.plist */, 120 | ); 121 | name = "Supporting Files"; 122 | sourceTree = ""; 123 | }; 124 | F2993F4144FC861DCA6F1AE0 /* Frameworks */ = { 125 | isa = PBXGroup; 126 | children = ( 127 | FFEF5216A43057972AB5A432 /* libPods-RNPusherClient.a */, 128 | ); 129 | name = Frameworks; 130 | sourceTree = ""; 131 | }; 132 | /* End PBXGroup section */ 133 | 134 | /* Begin PBXNativeTarget section */ 135 | 37AB3E551BA71D9100E08DFD /* RNPusherClient */ = { 136 | isa = PBXNativeTarget; 137 | buildConfigurationList = 37AB3E6A1BA71D9100E08DFD /* Build configuration list for PBXNativeTarget "RNPusherClient" */; 138 | buildPhases = ( 139 | 765EE6FB2360995256256E24 /* Check Pods Manifest.lock */, 140 | 37AB3E521BA71D9100E08DFD /* Sources */, 141 | 37AB3E531BA71D9100E08DFD /* Frameworks */, 142 | 37AB3E541BA71D9100E08DFD /* CopyFiles */, 143 | 4194F8C77AD5FBC8A4F1B251 /* Copy Pods Resources */, 144 | ); 145 | buildRules = ( 146 | ); 147 | dependencies = ( 148 | ); 149 | name = RNPusherClient; 150 | productName = RNPusherClient; 151 | productReference = 37AB3E561BA71D9100E08DFD /* libRNPusherClient.a */; 152 | productType = "com.apple.product-type.library.static"; 153 | }; 154 | 37AB3E601BA71D9100E08DFD /* RNPusherClientTests */ = { 155 | isa = PBXNativeTarget; 156 | buildConfigurationList = 37AB3E6D1BA71D9100E08DFD /* Build configuration list for PBXNativeTarget "RNPusherClientTests" */; 157 | buildPhases = ( 158 | 37AB3E5D1BA71D9100E08DFD /* Sources */, 159 | 37AB3E5E1BA71D9100E08DFD /* Frameworks */, 160 | 37AB3E5F1BA71D9100E08DFD /* Resources */, 161 | ); 162 | buildRules = ( 163 | ); 164 | dependencies = ( 165 | 37AB3E641BA71D9100E08DFD /* PBXTargetDependency */, 166 | ); 167 | name = RNPusherClientTests; 168 | productName = RNPusherClientTests; 169 | productReference = 37AB3E611BA71D9100E08DFD /* RNPusherClientTests.xctest */; 170 | productType = "com.apple.product-type.bundle.unit-test"; 171 | }; 172 | /* End PBXNativeTarget section */ 173 | 174 | /* Begin PBXProject section */ 175 | 37AB3E4E1BA71D9100E08DFD /* Project object */ = { 176 | isa = PBXProject; 177 | attributes = { 178 | LastUpgradeCheck = 0640; 179 | ORGANIZATIONNAME = Tackk; 180 | TargetAttributes = { 181 | 37AB3E551BA71D9100E08DFD = { 182 | CreatedOnToolsVersion = 6.4; 183 | }; 184 | 37AB3E601BA71D9100E08DFD = { 185 | CreatedOnToolsVersion = 6.4; 186 | }; 187 | }; 188 | }; 189 | buildConfigurationList = 37AB3E511BA71D9100E08DFD /* Build configuration list for PBXProject "RNPusherClient" */; 190 | compatibilityVersion = "Xcode 3.2"; 191 | developmentRegion = English; 192 | hasScannedForEncodings = 0; 193 | knownRegions = ( 194 | en, 195 | ); 196 | mainGroup = 37AB3E4D1BA71D9100E08DFD; 197 | productRefGroup = 37AB3E571BA71D9100E08DFD /* Products */; 198 | projectDirPath = ""; 199 | projectRoot = ""; 200 | targets = ( 201 | 37AB3E551BA71D9100E08DFD /* RNPusherClient */, 202 | 37AB3E601BA71D9100E08DFD /* RNPusherClientTests */, 203 | ); 204 | }; 205 | /* End PBXProject section */ 206 | 207 | /* Begin PBXResourcesBuildPhase section */ 208 | 37AB3E5F1BA71D9100E08DFD /* Resources */ = { 209 | isa = PBXResourcesBuildPhase; 210 | buildActionMask = 2147483647; 211 | files = ( 212 | ); 213 | runOnlyForDeploymentPostprocessing = 0; 214 | }; 215 | /* End PBXResourcesBuildPhase section */ 216 | 217 | /* Begin PBXShellScriptBuildPhase section */ 218 | 4194F8C77AD5FBC8A4F1B251 /* Copy Pods Resources */ = { 219 | isa = PBXShellScriptBuildPhase; 220 | buildActionMask = 2147483647; 221 | files = ( 222 | ); 223 | inputPaths = ( 224 | ); 225 | name = "Copy Pods Resources"; 226 | outputPaths = ( 227 | ); 228 | runOnlyForDeploymentPostprocessing = 0; 229 | shellPath = /bin/sh; 230 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RNPusherClient/Pods-RNPusherClient-resources.sh\"\n"; 231 | showEnvVarsInLog = 0; 232 | }; 233 | 765EE6FB2360995256256E24 /* Check Pods Manifest.lock */ = { 234 | isa = PBXShellScriptBuildPhase; 235 | buildActionMask = 2147483647; 236 | files = ( 237 | ); 238 | inputPaths = ( 239 | ); 240 | name = "Check Pods Manifest.lock"; 241 | outputPaths = ( 242 | ); 243 | runOnlyForDeploymentPostprocessing = 0; 244 | shellPath = /bin/sh; 245 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 246 | showEnvVarsInLog = 0; 247 | }; 248 | /* End PBXShellScriptBuildPhase section */ 249 | 250 | /* Begin PBXSourcesBuildPhase section */ 251 | 37AB3E521BA71D9100E08DFD /* Sources */ = { 252 | isa = PBXSourcesBuildPhase; 253 | buildActionMask = 2147483647; 254 | files = ( 255 | 37AB3E5C1BA71D9100E08DFD /* RNPusherClient.m in Sources */, 256 | ); 257 | runOnlyForDeploymentPostprocessing = 0; 258 | }; 259 | 37AB3E5D1BA71D9100E08DFD /* Sources */ = { 260 | isa = PBXSourcesBuildPhase; 261 | buildActionMask = 2147483647; 262 | files = ( 263 | ); 264 | runOnlyForDeploymentPostprocessing = 0; 265 | }; 266 | /* End PBXSourcesBuildPhase section */ 267 | 268 | /* Begin PBXTargetDependency section */ 269 | 37AB3E641BA71D9100E08DFD /* PBXTargetDependency */ = { 270 | isa = PBXTargetDependency; 271 | target = 37AB3E551BA71D9100E08DFD /* RNPusherClient */; 272 | targetProxy = 37AB3E631BA71D9100E08DFD /* PBXContainerItemProxy */; 273 | }; 274 | /* End PBXTargetDependency section */ 275 | 276 | /* Begin XCBuildConfiguration section */ 277 | 37AB3E681BA71D9100E08DFD /* Debug */ = { 278 | isa = XCBuildConfiguration; 279 | buildSettings = { 280 | ALWAYS_SEARCH_USER_PATHS = NO; 281 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 282 | CLANG_CXX_LIBRARY = "libc++"; 283 | CLANG_ENABLE_MODULES = YES; 284 | CLANG_ENABLE_OBJC_ARC = YES; 285 | CLANG_WARN_BOOL_CONVERSION = YES; 286 | CLANG_WARN_CONSTANT_CONVERSION = YES; 287 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 288 | CLANG_WARN_EMPTY_BODY = YES; 289 | CLANG_WARN_ENUM_CONVERSION = YES; 290 | CLANG_WARN_INT_CONVERSION = YES; 291 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 292 | CLANG_WARN_UNREACHABLE_CODE = YES; 293 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 294 | COPY_PHASE_STRIP = NO; 295 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 296 | ENABLE_STRICT_OBJC_MSGSEND = YES; 297 | GCC_C_LANGUAGE_STANDARD = gnu99; 298 | GCC_DYNAMIC_NO_PIC = NO; 299 | GCC_NO_COMMON_BLOCKS = YES; 300 | GCC_OPTIMIZATION_LEVEL = 0; 301 | GCC_PREPROCESSOR_DEFINITIONS = ( 302 | "DEBUG=1", 303 | "$(inherited)", 304 | ); 305 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 306 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 307 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 308 | GCC_WARN_UNDECLARED_SELECTOR = YES; 309 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 310 | GCC_WARN_UNUSED_FUNCTION = YES; 311 | GCC_WARN_UNUSED_VARIABLE = YES; 312 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 313 | MTL_ENABLE_DEBUG_INFO = YES; 314 | ONLY_ACTIVE_ARCH = YES; 315 | SDKROOT = iphoneos; 316 | }; 317 | name = Debug; 318 | }; 319 | 37AB3E691BA71D9100E08DFD /* Release */ = { 320 | isa = XCBuildConfiguration; 321 | buildSettings = { 322 | ALWAYS_SEARCH_USER_PATHS = NO; 323 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 324 | CLANG_CXX_LIBRARY = "libc++"; 325 | CLANG_ENABLE_MODULES = YES; 326 | CLANG_ENABLE_OBJC_ARC = YES; 327 | CLANG_WARN_BOOL_CONVERSION = YES; 328 | CLANG_WARN_CONSTANT_CONVERSION = YES; 329 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 330 | CLANG_WARN_EMPTY_BODY = YES; 331 | CLANG_WARN_ENUM_CONVERSION = YES; 332 | CLANG_WARN_INT_CONVERSION = YES; 333 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 334 | CLANG_WARN_UNREACHABLE_CODE = YES; 335 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 336 | COPY_PHASE_STRIP = NO; 337 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 338 | ENABLE_NS_ASSERTIONS = NO; 339 | ENABLE_STRICT_OBJC_MSGSEND = YES; 340 | GCC_C_LANGUAGE_STANDARD = gnu99; 341 | GCC_NO_COMMON_BLOCKS = YES; 342 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 343 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 344 | GCC_WARN_UNDECLARED_SELECTOR = YES; 345 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 346 | GCC_WARN_UNUSED_FUNCTION = YES; 347 | GCC_WARN_UNUSED_VARIABLE = YES; 348 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 349 | MTL_ENABLE_DEBUG_INFO = NO; 350 | SDKROOT = iphoneos; 351 | VALIDATE_PRODUCT = YES; 352 | }; 353 | name = Release; 354 | }; 355 | 37AB3E6B1BA71D9100E08DFD /* Debug */ = { 356 | isa = XCBuildConfiguration; 357 | baseConfigurationReference = C17A75306941DEAD3DF224C8 /* Pods-RNPusherClient.debug.xcconfig */; 358 | buildSettings = { 359 | HEADER_SEARCH_PATHS = ( 360 | "$(inherited)", 361 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 362 | "$(SRCROOT)/../react-native/React/**", 363 | "$(SRCROOT)/node_modules/react-native/React/**", 364 | ); 365 | OTHER_LDFLAGS = "-ObjC"; 366 | PRODUCT_NAME = "$(TARGET_NAME)"; 367 | SKIP_INSTALL = YES; 368 | }; 369 | name = Debug; 370 | }; 371 | 37AB3E6C1BA71D9100E08DFD /* Release */ = { 372 | isa = XCBuildConfiguration; 373 | baseConfigurationReference = 61C228DC3C922571DD4AEB69 /* Pods-RNPusherClient.release.xcconfig */; 374 | buildSettings = { 375 | HEADER_SEARCH_PATHS = ( 376 | "$(inherited)", 377 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 378 | "$(SRCROOT)/../react-native/React/**", 379 | "$(SRCROOT)/node_modules/react-native/React/**", 380 | ); 381 | OTHER_LDFLAGS = "-ObjC"; 382 | PRODUCT_NAME = "$(TARGET_NAME)"; 383 | SKIP_INSTALL = YES; 384 | }; 385 | name = Release; 386 | }; 387 | 37AB3E6E1BA71D9100E08DFD /* Debug */ = { 388 | isa = XCBuildConfiguration; 389 | buildSettings = { 390 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 391 | FRAMEWORK_SEARCH_PATHS = ( 392 | "$(SDKROOT)/Developer/Library/Frameworks", 393 | "$(inherited)", 394 | ); 395 | GCC_PREPROCESSOR_DEFINITIONS = ( 396 | "DEBUG=1", 397 | "$(inherited)", 398 | ); 399 | INFOPLIST_FILE = RNPusherClientTests/Info.plist; 400 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 401 | PRODUCT_NAME = "$(TARGET_NAME)"; 402 | }; 403 | name = Debug; 404 | }; 405 | 37AB3E6F1BA71D9100E08DFD /* Release */ = { 406 | isa = XCBuildConfiguration; 407 | buildSettings = { 408 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 409 | FRAMEWORK_SEARCH_PATHS = ( 410 | "$(SDKROOT)/Developer/Library/Frameworks", 411 | "$(inherited)", 412 | ); 413 | INFOPLIST_FILE = RNPusherClientTests/Info.plist; 414 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 415 | PRODUCT_NAME = "$(TARGET_NAME)"; 416 | }; 417 | name = Release; 418 | }; 419 | /* End XCBuildConfiguration section */ 420 | 421 | /* Begin XCConfigurationList section */ 422 | 37AB3E511BA71D9100E08DFD /* Build configuration list for PBXProject "RNPusherClient" */ = { 423 | isa = XCConfigurationList; 424 | buildConfigurations = ( 425 | 37AB3E681BA71D9100E08DFD /* Debug */, 426 | 37AB3E691BA71D9100E08DFD /* Release */, 427 | ); 428 | defaultConfigurationIsVisible = 0; 429 | defaultConfigurationName = Release; 430 | }; 431 | 37AB3E6A1BA71D9100E08DFD /* Build configuration list for PBXNativeTarget "RNPusherClient" */ = { 432 | isa = XCConfigurationList; 433 | buildConfigurations = ( 434 | 37AB3E6B1BA71D9100E08DFD /* Debug */, 435 | 37AB3E6C1BA71D9100E08DFD /* Release */, 436 | ); 437 | defaultConfigurationIsVisible = 0; 438 | defaultConfigurationName = Release; 439 | }; 440 | 37AB3E6D1BA71D9100E08DFD /* Build configuration list for PBXNativeTarget "RNPusherClientTests" */ = { 441 | isa = XCConfigurationList; 442 | buildConfigurations = ( 443 | 37AB3E6E1BA71D9100E08DFD /* Debug */, 444 | 37AB3E6F1BA71D9100E08DFD /* Release */, 445 | ); 446 | defaultConfigurationIsVisible = 0; 447 | defaultConfigurationName = Release; 448 | }; 449 | /* End XCConfigurationList section */ 450 | }; 451 | rootObject = 37AB3E4E1BA71D9100E08DFD /* Project object */; 452 | } 453 | -------------------------------------------------------------------------------- /RNPusherClient.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /RNPusherClient.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /RNPusherClient/RNPusherClient.h: -------------------------------------------------------------------------------- 1 | // 2 | // RNPusherClient.h 3 | // RNPusherClient 4 | // 5 | // Created by Dan Horrigan on 9/14/15. 6 | // Copyright (c) 2015 Tackk. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "RCTBridgeModule.h" 12 | 13 | @interface RNPusherClient : NSObject 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /RNPusherClient/RNPusherClient.m: -------------------------------------------------------------------------------- 1 | // 2 | // RNPusherClient.m 3 | // RNPusherClient 4 | // 5 | // Created by Dan Horrigan on 9/14/15. 6 | // Copyright (c) 2015 Tackk. All rights reserved. 7 | // 8 | 9 | 10 | #import 11 | #import "RNPusherClient.h" 12 | #import "RCTBridgeModule.h" 13 | #import "RCTEventDispatcher.h" 14 | 15 | NSString *const PusherNewEvent = @"Pusher.NewEvent"; 16 | NSString *const PusherWillConnect = @"Pusher.WillConnect"; 17 | NSString *const PusherDidConnect = @"Pusher.DidConnect"; 18 | NSString *const PusherDidDisconnectWithError = @"Pusher.DidDisconnectWithError"; 19 | NSString *const PusherFailedWithError = @"Pusher.FailedWithError"; 20 | NSString *const PusherWillAutomaticallyReconnect = @"Pusher.WillAutomaticallyReconnect"; 21 | NSString *const PusherWillAuthorizeChannel = @"Pusher.WillAuthorizeChannel"; 22 | NSString *const PusherAuthorizationPayloadFromResponseData = @"Pusher.AuthorizationPayloadFromResponseData"; 23 | NSString *const PusherDidSubscribeToChannel = @"Pusher.DidSubscribeToChannel"; 24 | NSString *const PusherDidUnsubscribeFromChannel = @"Pusher.DidUnsubscribeFromChannel"; 25 | NSString *const PusherDidFailToSubscribeToChannel = @"Pusher.DidFailToSubscribeToChannel"; 26 | NSString *const PusherDidReceiveErrorEvent = @"Pusher.DidReceiveErrorEvent"; 27 | 28 | 29 | 30 | @implementation RNPusherClient 31 | { 32 | PTPusher *_client; 33 | NSString *_socketId; 34 | NSMutableDictionary *_bindings; 35 | } 36 | 37 | RCT_EXPORT_MODULE(); 38 | 39 | @synthesize bridge = _bridge; 40 | 41 | 42 | /** 43 | Connect to Pusher. 44 | 45 | @param apiKey The Pusher API key to connect with. 46 | */ 47 | RCT_EXPORT_METHOD(connect:(NSString *)apiKey) 48 | { 49 | _client = [PTPusher pusherWithKey:apiKey delegate:self encrypted:YES]; 50 | [_client connect]; 51 | 52 | _bindings = [[NSMutableDictionary alloc] init]; 53 | } 54 | 55 | 56 | /** 57 | Disconnect from Pusher. 58 | */ 59 | RCT_EXPORT_METHOD(disconnect) 60 | { 61 | [_client disconnect]; 62 | } 63 | 64 | 65 | /** 66 | Subscribe to a channel. 67 | 68 | @param channelName The channel to subscribe to. 69 | */ 70 | RCT_EXPORT_METHOD(subscribe:(NSString *)channelName) 71 | { 72 | PTPusherChannel *channel = [_client channelNamed:channelName]; 73 | 74 | if (! channel) { 75 | [_client subscribeToChannelNamed:channelName]; 76 | } 77 | } 78 | 79 | 80 | /** 81 | Unsubscribe from a channel. 82 | 83 | @param channelName The channel to unsubscribe from. 84 | */ 85 | RCT_EXPORT_METHOD(unsubscribe:(NSString *)channelName) 86 | { 87 | PTPusherChannel *channel = [_client channelNamed:channelName]; 88 | 89 | if (channel) { 90 | [channel unsubscribe]; 91 | } 92 | } 93 | 94 | 95 | /** 96 | Bind to an event in a channel. 97 | 98 | @param channelName The channel to bind the event on. 99 | @param eventName The name of the event to bind to. 100 | */ 101 | RCT_EXPORT_METHOD(bind:(NSString *)channelName withEventName:(NSString *)eventName) 102 | { 103 | PTPusherChannel *channel = [_client channelNamed:channelName]; 104 | 105 | if (channel) { 106 | 107 | PTPusherEventBinding *binding = [channel bindToEventNamed:eventName handleWithBlock:^(PTPusherEvent *channelEvent) { 108 | NSDictionary *event = @{ 109 | @"channel": channelEvent.channel, 110 | @"name": channelEvent.name, 111 | @"data": channelEvent.data 112 | }; 113 | [self.bridge.eventDispatcher sendAppEventWithName:PusherNewEvent 114 | body:event]; 115 | }]; 116 | 117 | NSString *keyName = [NSString stringWithFormat:@"%@-%@", channelName, eventName]; 118 | [_bindings setObject:binding forKey:keyName]; 119 | } 120 | } 121 | 122 | 123 | /** 124 | Unbind an event from the channel. 125 | 126 | @param channelName The channel to unbind the event from. 127 | @param eventName The name of the event to unbind. 128 | */ 129 | RCT_EXPORT_METHOD(unbind:(NSString *)channelName withEventName:(NSString *)eventName) 130 | { 131 | PTPusherChannel *channel = [_client channelNamed:channelName]; 132 | 133 | if (channel) { 134 | NSString *keyName = [NSString stringWithFormat:@"%@-%@", channelName, eventName]; 135 | PTPusherEventBinding *binding = [_bindings objectForKey:keyName]; 136 | 137 | if (binding) { 138 | [channel removeBinding:binding]; 139 | [_bindings removeObjectForKey:keyName]; 140 | } 141 | } 142 | } 143 | 144 | 145 | // Pusher Delegate Methods 146 | 147 | /** 148 | Notifies the delegate that the PTPusher instance is about to connect to the Pusher service. 149 | 150 | @param pusher The PTPusher instance that is connecting. 151 | @param connection The connection for the pusher instance. 152 | @return NO to abort the connection attempt. 153 | */ 154 | - (BOOL)pusher:(PTPusher *)pusher connectionWillConnect:(PTPusherConnection *)connection 155 | { 156 | [self.bridge.eventDispatcher sendAppEventWithName:PusherWillConnect body:nil]; 157 | 158 | return YES; 159 | } 160 | 161 | 162 | /** 163 | Notifies the delegate that the PTPusher instance has connected to the Pusher service successfully. 164 | 165 | @param pusher The PTPusher instance that has connected. 166 | @param connection The connection for the pusher instance. 167 | */ 168 | - (void)pusher:(PTPusher *)pusher connectionDidConnect:(PTPusherConnection *)connection 169 | { 170 | [self.bridge.eventDispatcher sendAppEventWithName:PusherDidConnect 171 | body:connection.socketID]; 172 | } 173 | 174 | 175 | /** 176 | Notifies the delegate that the PTPusher instance has disconnected from the Pusher service. 177 | 178 | Clients should check the value of the willAttemptReconnect parameter before trying to reconnect manually. 179 | In most cases, the client will try and automatically reconnect, depending on the error code returned by 180 | the Pusher service. 181 | 182 | If willAttemptReconnect is YES, clients can expect a pusher:connectionWillReconnect:afterDelay: message 183 | immediately following this one. Clients can return NO from that delegate method to cancel the automatic 184 | reconnection attempt. 185 | 186 | If the client has disconnected due to a fatal Pusher error (as indicated by the error code), 187 | willAttemptReconnect will be NO and the error domain will be `PTPusherFatalErrorDomain`. 188 | 189 | @param pusher The PTPusher instance that has connected. 190 | @param connection The connection for the pusher instance. 191 | @param error If the connection disconnected abnormally, error will be non-nil. 192 | @param willAttemptReconnect YES if the client will try and reconnect automatically. 193 | */ 194 | - (void)pusher:(PTPusher *)pusher connection:(PTPusherConnection *)connection didDisconnectWithError:(NSError *)error willAttemptReconnect:(BOOL)willAttemptReconnect 195 | { 196 | // Have to send an object as the event body, so we turn the BOOL into an NSNumber 197 | NSNumber *willReconnect = [NSNumber numberWithBool:willAttemptReconnect]; 198 | 199 | [self.bridge.eventDispatcher sendAppEventWithName:PusherDidDisconnectWithError body:willReconnect]; 200 | } 201 | 202 | 203 | /** 204 | Notifies the delegate that the PTPusher instance failed to connect to the Pusher service. 205 | 206 | In the case of connection failures, the client will *not* attempt to reconnect automatically. 207 | Instead, clients should implement this method and check the error code and manually reconnect 208 | the client if it makes sense to do so. 209 | 210 | @param pusher The PTPusher instance that has connected. 211 | @param connection The connection for the pusher instance. 212 | @param error The connection error. 213 | */ 214 | - (void)pusher:(PTPusher *)pusher connection:(PTPusherConnection *)connection failedWithError:(NSError *)error 215 | { 216 | [self.bridge.eventDispatcher sendAppEventWithName:PusherDidDisconnectWithError body:@{ 217 | @"code": [NSNumber numberWithLong:error.code], 218 | @"error": error.localizedDescription, 219 | @"userInfo": error.userInfo, 220 | }]; 221 | } 222 | 223 | 224 | /** 225 | Notifies the delegate that the PTPusher instance will attempt to automatically reconnect. 226 | 227 | You may wish to use this method to keep track of the number of automatic reconnection attempts and abort after a fixed number. 228 | 229 | @param pusher The PTPusher instance that has connected. 230 | @param connection The connection for the pusher instance. 231 | @return NO if you do not want the client to attempt an automatic reconnection. 232 | */ 233 | - (BOOL)pusher:(PTPusher *)pusher connectionWillAutomaticallyReconnect:(PTPusherConnection *)connection afterDelay:(NSTimeInterval)delay 234 | { 235 | NSNumber *delaySeconds = [NSNumber numberWithDouble:delay]; 236 | 237 | [self.bridge.eventDispatcher sendAppEventWithName:PusherWillAutomaticallyReconnect body:delaySeconds]; 238 | 239 | return YES; 240 | } 241 | 242 | 243 | /** 244 | Notifies the delegate of the request that will be used to authorize access to a channel. 245 | 246 | When using the Pusher Javascript client, authorization typically relies on an existing session cookie 247 | on the server; when the Javascript client makes an AJAX POST to the server, the server can return 248 | the user's credentials based on their current session. 249 | 250 | When using libPusher, there will likely be no existing server-side session; authorization will 251 | need to happen by some other means (e.g. an authorization token or HTTP basic auth). 252 | 253 | By implementing this delegate method, you will be able to set any credentials as necessary by 254 | modifying the request as required (such as setting POST parameters or headers). 255 | 256 | @param pusher The PTPusher instance that is requesting authorization 257 | @param channel The channel that requires authorizing 258 | @param request A mutable URL request that will be POSTed to the configured `authorizationURL` 259 | */ 260 | - (void)pusher:(PTPusher *)pusher willAuthorizeChannel:(PTPusherChannel *)channel withRequest:(NSMutableURLRequest *)request 261 | { 262 | [self.bridge.eventDispatcher sendAppEventWithName:PusherWillAuthorizeChannel body:nil]; 263 | } 264 | 265 | 266 | /** 267 | Allows the delegate to return authorization data in the format required by Pusher from a 268 | non-standard respnse. 269 | 270 | When using a remote server to authorize access to a private channel, the server is expected to 271 | return an authorization payload in a specific format which is then sent to Pusher when connecting 272 | to a private channel. 273 | 274 | Sometimes, a server might return a non-standard response, for example, the auth data may be a sub-set 275 | of some bigger response. 276 | 277 | If implemented, Pusher will call this method with the response data returned from the authorization 278 | URL and will use whatever dictionary is returned instead. 279 | */ 280 | - (NSDictionary *)pusher:(PTPusher *)pusher authorizationPayloadFromResponseData:(NSDictionary *)responseData 281 | { 282 | [self.bridge.eventDispatcher sendAppEventWithName:PusherAuthorizationPayloadFromResponseData body:responseData]; 283 | 284 | return responseData; 285 | } 286 | 287 | 288 | /** 289 | Notifies the delegate that the PTPusher instance has subscribed to the specified channel. 290 | 291 | This method will be called after any channel authorization has taken place and when a subscribe event has been received. 292 | 293 | @param pusher The PTPusher instance that has connected. 294 | @param channel The channel that was subscribed to. 295 | */ 296 | - (void)pusher:(PTPusher *)pusher didSubscribeToChannel:(PTPusherChannel *)channel 297 | { 298 | [self.bridge.eventDispatcher sendAppEventWithName:PusherDidSubscribeToChannel body:channel.name]; 299 | } 300 | 301 | 302 | /** 303 | Notifies the delegate that the PTPusher instance has unsubscribed from the specified channel. 304 | 305 | This method will be called immediately after unsubscribing from a channel. 306 | 307 | @param pusher The PTPusher instance that has connected. 308 | @param channel The channel that was unsubscribed from. 309 | */ 310 | - (void)pusher:(PTPusher *)pusher didUnsubscribeFromChannel:(PTPusherChannel *)channel 311 | { 312 | [self.bridge.eventDispatcher sendAppEventWithName:PusherDidUnsubscribeFromChannel body:channel.name]; 313 | } 314 | 315 | 316 | /** 317 | Notifies the delegate that the PTPusher instance failed to subscribe to the specified channel. 318 | 319 | The most common reason for subscribing failing is authorization failing for private/presence channels. 320 | 321 | @param pusher The PTPusher instance that has connected. 322 | @param channel The channel that was subscribed to. 323 | @param error The error returned when attempting to subscribe. 324 | */ 325 | - (void)pusher:(PTPusher *)pusher didFailToSubscribeToChannel:(PTPusherChannel *)channel withError:(NSError *)error 326 | { 327 | [self.bridge.eventDispatcher sendAppEventWithName:PusherDidFailToSubscribeToChannel body:@{ 328 | @"code": [NSNumber numberWithLong:error.code], 329 | @"error": error.localizedDescription, 330 | @"userInfo": error.userInfo, 331 | }]; 332 | } 333 | 334 | 335 | /** 336 | Notifies the delegate that an error event has been received. 337 | 338 | If a client is binding to all events, either through the client or using NSNotificationCentre, they will also 339 | receive notification of this event like any other. 340 | 341 | @param pusher The PTPusher instance that received the event. 342 | @param errorEvent The error event. 343 | */ 344 | - (void)pusher:(PTPusher *)pusher didReceiveErrorEvent:(PTPusherErrorEvent *)errorEvent 345 | { 346 | [self.bridge.eventDispatcher sendAppEventWithName:PusherDidReceiveErrorEvent body:@{ 347 | @"code": [NSNumber numberWithLong:errorEvent.code], 348 | @"error": errorEvent.message, 349 | }]; 350 | } 351 | 352 | @end 353 | -------------------------------------------------------------------------------- /RNPusherClientTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.tackk.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-pusher", 3 | "version": "1.0.0", 4 | "description": "Pusher client for React Native", 5 | "main": "Client.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/tackk/react-native-pusher.git" 12 | }, 13 | "author": "Dan Horrigan", 14 | "license": "MIT", 15 | "bugs": { 16 | "url": "https://github.com/tackk/react-native-pusher/issues" 17 | }, 18 | "homepage": "https://github.com/tackk/react-native-pusher#readme", 19 | "devDependencies": { 20 | "react-native": ">=0.10.0" 21 | }, 22 | "peerDependencies": { 23 | "react-native": ">=0.10.0" 24 | }, 25 | } 26 | --------------------------------------------------------------------------------