- Publish and Subscribe Always-on Socket Cloud
- One-to-Many / One-to-One / Platform Ubiquitous Cloud
- Globally Distributed Cloud Network - Many Datacenters World-Wide - Fastest Connections
- Optimized for Mobile and Web - iPhone, Android, Chrome, Firefox, IE and more.
- Locksetp Synchronization with Everyone on Earth - Synchronize Mass Audiences.
PubNub is a client-to-client push service in the cloud. Connect Everything to Everything; literally! This is a cloud-based service for broadcasting Real-time messages to millions of web and mobile clients simultaneously.
- Twitter: http://twitter.com/PubNub
- Website: http://www.pubnub.com
- Videos: http://www.youtube.com/playlist?p=PLF0BA2B6DAAF4FBBF
- Socket.IO: https://github.com/pubnub/pubnub-api/tree/master/socket.io
- Showcase: http://www.pubnub.com/blog
- Interview: http://techzinglive.com/?p=227
- Earth Scale Deployment - Your App scales with ease.
- Many Datacenters World Wide - High Performance everywhere on Earth.
- Optimized for Slow and Fast Connections - Fast for mobile 3G, WiFi, 4G and Edge.
- Reliable Message Delivery on Unreliable connections.
- Compression and Bundling - Faster than WebSockets - up to 100msg per second faster.
- PHP, Ruby, JavaScript and more - All Streamlined Platforms Supported.
- The API FAST! - iPhone, Android and Blackberry phones zip!
- It's a Breeze for Mobile Phones - Quick and Easy Development.
- Mass Broadcasting Replication - Send a message to Millions of People in Milliseconds.
- Platform Ubiquitous Cloud - Every Platform Now has a way to communicate Instantly.
- Cross Device Communication - Androids and iPhones and Browsers -- all connected.
Use this section of the README to review the current specification for PubNub Cloud Client Libraries. The pseudocode will guide you in learning how each client library must act in order to properly support the breadth of features powered by PubNub Cloud. Most client libraries are already written! So go check out the list of libraries already available.
- Must be able to communicate with EVERY other PubNub Client Lib.
- Must be Non-blocking (Asynchronous) on all I/O.
- Must use single Dictionary/Object as Parameter for all methods.
- Must follow guides in this README file including method usage patterns.
- Includes a Full Unit Test with a test of each method.
- Includes Quick Usage Doc with Example Copy/Paste Code.
There are support libs that are needed in order to provide full implementation of a PubNub Client API. Here is a list of all needed external imports common to most platforms and programming languages.
- Crypto Standford AES - Client Side Encryption/Decryption
- TLS/SSL 2048bit Support or Better
- HashLib for SHA256
- Async HTTP/HTTPS or Async TCP Sockets (Non-Blocking)
- JSON Encode/Decode or Stringify/Parse
- ZLib for GZIP
- UUID for Unique ID Generation
- URL Encode
- Events Fire/Bind/Unbind
- init()
- time()
- uuid()
- publish()
- subscribe()
- unsubscribe()
- history()
Create a new PubNub Entity for Publishing/Subscribing. This entity associates itself with account-level credentials and a selected origin. Also Security Options are Specified.
var pubnub = PubNub.init({
publish_key : "CUSTOMER_PUBLISH_KEY",
subscribe_key : "CUSTOMER_SUBSCRIBE_KEY",
secret_key : "CUSTOMER_SECRET_KEY",
ssl : true,
cipher_key : "AES-Standford-Crypto-Cipher-Key",
origin : "pubsub.pubnub.com"
})
This function is a utility only and has not functional value other than a PING to the PubNub Cloud.
PubNub.time(function(time){
log(time)
})
Utility function for generating a UUID.
PubNub.uuid(function(uuid){
log(uuid)
})
Broadcast a message on a specific channel. The message may be any valid JSON value including:
- Dictionary (Objects).
- Strings.
- Numbers.
PubNub.publish({
channel : "hello_world",
message : "Hi.",
callback : function(response) { log(response) }
})
Listen for messages on a specified channel. Register events for receiving messages, connecting, disconnecting and reconnecting after an unintended disconnect.
PubNub.subscribe({
channel : "my-channel",
callback : function(message) { log(message) },
connect : function() { log("Connected") },
disconnect : function() { log("Disconnected") },
reconnect : function() { log("Reconnected") }
})
Stop Listen for messages on a specified channel.
PubNub.unsubscribe({
channel : "my-channel"
})
Retrieve past messages sent through the system.
PubNub.history({
channel : "my-channel",
limit : 100,
callback : (messages) { log(messages) }
})
/time/0
GET /time/0 HTTP/1.1
[7529152783414]
This is a special HTTP Request that holds the connection and response until a message is published or the connection timer fires a timetoken update.
- Send First Request.
- Receive a snazzy new TimeToken.
- Send Second Request with Last Received new snazzy TimeToken.
- Receive a response after X Minutes with array of Messages (may be empty) and new TimeToken.
- Repeat #2-#5 forever until UNSUBSCRIBE()
/subscribe/subscribe_key/channel/0/timetoken
GET /subscribe/demo/my-channel/0/0 HTTP/1.1
[[],"7529152783414"]
GET /subscribe/demo/my-channel/0/7529152783414 HTTP/1.1
[[MSG,MSG,MSG],"75291527861853"]
[[],"75291527861853"]
/publish/pub-key/sub-key/sha256-signature/channel/0/json
GET /publish/demo/demo/e0991b12871de57b333fd0c992f7d3112577cf62/my-channel/0/{"msg":"hi"} HTTP/1.1
[1,"D"]
The Publish Response always returns success transmission details.
The First element of the response Array is a bool value either 0
or 1
.
0
means failure and 1
means successful transmission.
If the response code is 0
, then the transmission has failed.
In the condition of a failed transmission, an explanation is provided
in the second element of the response array.
[1,"D"]
[0,"Reason for Failure Shown Here"]
- "Disconnected" - The network has gone away.
- "Message Too Big" - Max message size exceeded.
- "Invalid Publish Key" - Wrong Publish Key was Used.
- "Invalid Message Signature" - The message was SHA256 Signed incorrectly.
History API will allow you to fetch previously published messages. Currently you can only fetch the last 100 messages. However soon-to-come features will include forever-history fetching.
/history/sub-key/channel/0/limit
GET /history/demo/my-channel/0/100 HTTP/1.1
[MSG,MSG,MSG]
All functions are required to be non-blocking.
All I/O must be Asynchronous.
Threads are okay
however SOCKET LOOPS are much preferred.
Examples of Good Socket Loop libs are:
- Twisted (Python)
- Tornado (Python)
- Node.JS (JavaScript)
- Event::Machine (Ruby)
- LibEvent (C)
- LibEV (C)
- Any::Event (Perl)
- POE::Async (Perl)
Any executed function must not stop the execution stack. If a return value is needed from a function call, then a callback function is required to be a parameter of the function -- and the return value is supplied to the callback.
Publish and Subscribe require significant amounts of checks in order to provide for easy use to the developer using the API. Show as follows are the Publish and Subscribe functions which have basic Pseudocode Logic Requirements:
def publish( self, args ) :
## Fail if bad input.
if not (args['channel'] and args['message']) :
print('Missing Channel or Message')
return False
## Capture User Input
channel = args['channel']
if self.cipher_key:
message = json.dumps(EncodeAES( self.cipher_key, args['message'] ))
else :
message = json.dumps(args['message'])
## Capture Callback
if args.has_key('callback') :
callback = args['callback']
else :
callback = lambda x : x
## Sign Message
if self.secret_key :
signature = hmac.new( self.secret_key, '/'.join([
self.publish_key,
self.subscribe_key,
channel,
message
]), hashlib.sha256 ).hexdigest()
else :
signature = '0'
## Send Message
self._request([
'publish',
self.publish_key,
self.subscribe_key,
signature,
URL_ENCODE(channel),
'0',
URL_ENCODE(message)
], callback )
def subscribe( self, args ) :
## Fail if missing channel
if not 'channel' in args :
print('Missing Channel.')
return False
## Fail if missing callback
if not 'callback' in args :
print('Missing Callback.')
return False
## Capture User Input
channel = URL_ENCODE(args['channel'])
callback = args['callback']
connectcb = args['connect'] or lambda x:x
disconnectcb = args['disconnect'] or lambda x:x
reconnectcb = args['reconnect'] or lambda x:x
if 'errorback' in args:
errorback = args['errorback']
else:
errorback = lambda x: x
## New Channel?
if not (channel in self.subscriptions) :
self.subscriptions[channel] = {
'first' : False,
'connected' : 0,
'disconnected' : 0,
'timetoken' : '0'
}
## Ensure Single Connection
if self.subscriptions[channel]['connected'] :
print("Already Connected")
return False
self.subscriptions[channel]['connected'] = 1
## Subscription TimeStack
def receive():
## STOP CONNECTION?
if not self.subscriptions[channel]['connected']:
return
def sub_callback(response):
## STOP CONNECTION?
if not self.subscriptions[channel]['connected']:
return
## CONNECTED CALLBACK
if not self.subscriptions[channel]['first'] :
self.subscriptions[channel]['first'] = True
connectcb()
## PROBLEM?
if not response:
## Disconnect
if not self.subscriptions[channel]['disconnected']:
self.subscriptions[channel]['disconnected'] = 1
disconnectcb()
def time_callback(_time):
if not _time:
reactor.callLater(time.time()+1, receive)
return errorback("Lost Network Connection")
else:
reactor.callLater(time.time()+1, receive)
## ENSURE CONNECTED (Call Time Function)
return self.time({ 'callback' : time_callback })
else:
## Reconnect
if self.subscriptions[channel]['disconnected']:
self.subscriptions[channel]['disconnected'] = 0
reconnectcb()
self.subscriptions[channel]['timetoken'] = response[1]
reactor.callLater(time.time()+0.0001, receive)
for message in response[0]:
if self.cipher_key:
callback(json.loads(DecodeAES( self.cipher_key, message )))
else:
callback(json.loads(message))
## CONNECT TO PUBNUB SUBSCRIBE SERVERS
try :
self._request( [
'subscribe',
self.subscribe_key,
channel,
'0',
str(self.subscriptions[channel]['timetoken'])
], sub_callback )
except :
reactor.callLater(time.time()+1, receive)
return
## BEGIN SUBSCRIPTION (LISTEN FOR MESSAGES)
receive()