Skip to content

Instantly share code, notes, and snippets.

@django-wong
Last active August 29, 2015 14:18
Show Gist options
  • Save django-wong/f158570028bc87a2a5aa to your computer and use it in GitHub Desktop.
Save django-wong/f158570028bc87a2a5aa to your computer and use it in GitHub Desktop.
Websocket connecter - Javascript
/**
* Common websocket connecter, only compliant with rapAthorus
* #events
* online
* offline
* onmessage
* connect_failed
* get_token_failed
* other custom events...
*/
var Connecter = function(options){
'use strict';
options = options || {};
this.token = options.token || undefined;
this.host = options.host || undefined;
this.port = options.port || 8081;
this.path = options.path || '/connect';
this.get_token_counter = 0;
this.ws = undefined;
this.events = {};
this.connected = undefined;
this.online = undefined;
this.queue = [];
this.retryCount = 0;
this.loginCount = 0;
var connecter = this;
connecter.getToken = function(cb) {
cb = cb || function(){};
// connecter.get_token_counter++;
var options ={
url: '/member/token',
cache: false,
dataType: 'json',
success: function(data){
if(!data.error){
connecter.get_token_counter = 0;
connecter.token = data.token;
connecter.expires = data.expires;
connecter.trigger('get_token_success', connecter.token);
}
cb.call(connecter);
},
error: function(data){
cb.call(connecter);
}
};
connecter.ajax(options);
};
connecter.getIPv4 = function(cb){
var options ={
url: '/home/ip',
async: false,
cache: false,
dataType: 'text',
success: function(data){
connecter.host = data;
cb.call(connecter);
},
error: function(data){
cb.call(connecter);
}
};
connecter.ajax(options);
};
connecter.connect = function() {
connecter.retryCount ++;
if(!connecter.token && connecter.retryCount<3){
connecter.getToken(connecter.connect);
return;
}
if(!connecter.host && connecter.retryCount<3){
connecter.getIPv4(connecter.connect);
}
connecter.retryCount = 0;
if(connecter.ws && connecter.connected){
connecter.ws.close();
connecter.ws = undefined;
}
connecter.ws = new WebSocket("ws://"+connecter.host+":"+connecter.port+connecter.path);
connecter.ws.onopen = connecter.logon;
connecter.ws.onmessage = connecter.onmessage;
connecter.ws.onclose = connecter.onclose;
connecter.ws.onerror = connecter.onerror;
};
connecter.logon = function(evt) {
connecter.loginCount = 0;
if(!connecter.connected){
connecter.connected = true;
connecter.trigger('connected');
console.log('connected');
}
var logon_info = new connecter.message('logon');
logon_info.signature = connecter.logonSignature(logon_info);
connecter.send(JSON.stringify(logon_info));
};
connecter.onmessage = function(evt) {
var message = evt.data;
connecter.trigger('onmessage', message);
try{
message = JSON.parse(message);
}catch(e){
message = evt.data;
}
if(typeof(message) === 'object'){
if(message.handle !== undefined && message.handle !== ''){
connecter.trigger(message.handle, message);
}else if(message.error){
console.log(message.error);
if(message.code){
switch(message.code){
case 1:{
if(connecter.loginCount < 5){
connecter.loginCount +=1;
connecter.getToken(connecter.logon);
}
break;
}
case 2:{
if(connecter.loginCount < 5){
connecter.loginCount +=1;
connecter.getToken(connecter.logon);
}
break;
}
default :{
connecter.trigger('onerror', message);
console.info('Unexpected error code');
}
}
}
}
}else{
switch(message){
case 'logon_success': {
connecter.trigger('online');
connecter.online = true;
connecter.process();
break;
}
default: {
break;
}
}
}
};
connecter.onclose = function(evt) {
connecter.connected = false;
connecter.online = false;
console.log('connection has been closed');
connecter.trigger('offline');
};
connecter.onerror = function(evt) {
connecter.trigger('onerror', evt);
};
/**
* Send text
* @param mixed data usual is meessage object or support json plaintext
* @return void
*/
connecter.send = function(data, callback) {
if(connecter.ws.readyState !== 1){
connecter.queue.push({'data': data, 'callback':callback});
}else{
if(typeof(data) !== 'string'){
data = JSON.stringify(data);
}
connecter.ws.send(data);
if(callback && typeof(callback) == 'function'){
callback.call(this);
}
}
};
/**
* process the queue
* @return {[type]} [description]
*/
connecter.process = function(){
for(var i in connecter.queue){
var q = connecter.queue[i];
connecter.send(q.data, q.callback);
}
connecter.queue = [];
};
/**
* Send a ajax request, alias for $.ajax()
* @param object o ajax options
* @return void
*/
connecter.ajax = function(o){
var options = {
};
options = $.extend(options, o);
$.ajax(options);
};
/**
* Output string
* @param string text
* @return void
*/
connecter.alert = function(text) {
console.info(text);
};
/**
* Get current time stamp
* @return int timestamp
*/
connecter.currentTime = function(){
return parseInt(new Date().valueOf()/1000);
};
/**
* Signature a logon message
* @param object logon message object
* @return string signature
*/
connecter.logonSignature = function(logon) {
var str = logon.token+logon.timestamp+'';
str = str.toLowerCase();
var signature = MD5(str).toLowerCase();
return signature;
};
/**
* Trigger a custom event
* @param string event name
* @params any params you want deliver
* @return connecter
*/
connecter.trigger = function(){
var args = Array.prototype.slice.call(arguments);
var evt = args.shift();
if(!connecter.events[evt]){
connecter.events[evt] = [];
}
var es = connecter.events[evt];
for (var j in es) {
var func = es[j];
func.apply(connecter, args);
}
return connecter;
};
/**
* bind a custom event
* @param string evt event name
* @param function callback
* @return connecter
*/
connecter.bind = function(evt, callback){
if(!connecter.events[evt]){
connecter.events[evt] = [];
}
var e = connecter.events[evt];
e.push(callback);
return connecter;
};
/**
* unbind a custom event
* @param string evt event name
* @param function callback witch you want unbind
* @return connecter
*/
connecter.unbind = function(evt, callback){
if(evt === true){
connecter.events = {};
return connecter;
}
if(!connecter.events[evt]){
return connecter;
}
if(callback === undefined){
connecter.events[evt] = [];
return connecter;
}
var es = connecter.events[evt];
for(var i in es){
if(es[i] === callback){
connecter.events[evt].splice(i,1);
}
}
connecter.alert(connecter.events);
return connecter;
};
/**
* Standard message object
* @param string handle
* @param mixed body
* @return object
*/
connecter.message = function(handle, body){
if(connecter.expires < connecter.currentTime()){
connecter.getToken();
}
var data = {
'token' : connecter.token,
'timestamp' : connecter.currentTime(),
'body' : body,
'handle' : handle,
};
return data;
};
/**
* Handle login request
* @param object message should be a json object
* @return void
*/
connecter.handle_login = function(message){
if(message.body === 'success'){
connecter.loginCount = 0;
connecter.trigger('online');
connecter.online = true;
console.info('online');
connecter.process();
}
};
/**
* init connecter, bind login handler
* @return connecter
*/
connecter.init = function(){
connecter.bind('login', connecter.handle_login);
return connecter;
};
return connecter.init();
};
var conn = new Connecter({'host': ipaddress, 'token': token});
conn.connect();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment