Skip to content

Instantly share code, notes, and snippets.

@euforic
Last active March 15, 2017 14:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save euforic/5751161 to your computer and use it in GitHub Desktop.
Save euforic/5751161 to your computer and use it in GitHub Desktop.
Simple Socket Wrapper for Titanium
/*!
* Event Emitters
*/
/**
* Initialize a new `Emitter`.
*
* @api public
*/
function Emitter(obj) {
if (obj) { return mixin(obj); }
}
/**
* Mixin the emitter properties.
*
* @param {Object} obj
* @return {Object}
* @api private
*/
function mixin(obj) {
for (var key in Emitter.prototype) {
obj[key] = Emitter.prototype[key];
}
return obj;
}
/**
* Listen on the given `event` with `fn`.
*
* @param {String} event
* @param {Function} fn
* @return {Emitter}
* @api public
*/
Emitter.prototype.on = function(event, fn){
this._callbacks = this._callbacks || {};
(this._callbacks[event] = this._callbacks[event] || [])
.push(fn);
return this;
};
/**
* Adds an `event` listener that will be invoked a single
* time then automatically removed.
*
* @param {String} event
* @param {Function} fn
* @return {Emitter}
* @api public
*/
Emitter.prototype.once = function(event, fn){
var self = this;
this._callbacks = this._callbacks || {};
function on() {
self.off(event, on);
fn.apply(this, arguments);
}
fn._off = on;
this.on(event, on);
return this;
};
/**
* Remove the given callback for `event` or all
* registered callbacks.
*
* @param {String} event
* @param {Function} fn
* @return {Emitter}
* @api public
*/
Emitter.prototype.off = function(event, fn){
this._callbacks = this._callbacks || {};
var callbacks = this._callbacks[event];
if (!callbacks) { return this; }
// remove all handlers
if (1 == arguments.length) {
delete this._callbacks[event];
return this;
}
// remove specific handler
var i = callbacks.indexOf(fn._off || fn);
if (~i) { callbacks.splice(i, 1); }
return this;
};
/**
* Emit `event` with the given args.
*
* @param {String} event
* @param {Mixed} ...
* @return {Emitter}
* @api public
*/
Emitter.prototype.emit = function(event){
this._callbacks = this._callbacks || {};
var args = [].slice.call(arguments, 1);
var callbacks = this._callbacks[event];
if (callbacks) {
callbacks = callbacks.slice(0);
for (var i = 0, len = callbacks.length; i < len; ++i) {
callbacks[i].apply(this, args);
}
}
return this;
};
/**
* Return array of callbacks for `event`.
*
* @param {String} event
* @return {Array}
* @api public
*/
Emitter.prototype.listeners = function(event){
this._callbacks = this._callbacks || {};
return this._callbacks[event] || [];
};
/**
* Check if this emitter has `event` handlers.
*
* @param {String} event
* @return {Boolean}
* @api public
*/
Emitter.prototype.hasListeners = function(event){
return !! this.listeners(event).length;
};
/**
* Expose `Socket`.
*/
if (typeof module !== 'undefined') {
module.exports = Socket;
}
/**
* [Socket description]
* @param {[type]} opts [description]
*/
function Socket(opts) {
if (!(this instanceof Socket)){ return new Socket(opts); }
opts = opts || {};
this.timeout = 5000;
this.host = opts.host;
this.port = opts.port;
this.retry = opts.retry;
this.bytesRead = 0;
this.bytesWritten = 0;
this.ignore = [];
}
/**
* Inherit from `Emitter.prototype`.
*/
Socket.prototype.__proto__ = Emitter.prototype;
/**
* [connect description]
* @param {[type]} opts [description]
* @param {Function} fn [description]
* @return {[type]} [description]
*/
Socket.prototype.connect = function(opts, fn){
var self = this;
opts = opts || {};
var reConnect = !!opts.reConnect;
if ('function' == typeof opts) {
fn = opts;
opts = {};
}
self.host = opts.host || self.host || '127.0.0.1';
self.port = opts.port || self.port;
self.retry = opts.retry || self.retry;
this._proxy = Ti.Network.Socket.createTCP({
host: self.host,
port: self.port,
connected: function (e) {
self.connected = true;
self._connection = e.socket;
fn && fn(e);
self.emit(((reConnect) ? 'reconnect' : 'connect'), e);
Ti.Stream.pump(e.socket, function(e){
if (e.bytesProcessed < 0) {
self.close(true);
return;
}
self.emit('data', '' + e.buffer);
}, 1024, true);
},
error: function(e) {
var err = { code: e.errorCode, error: e.error };
if (!~self.ignore.indexOf(err.code)) { return self.emit('error', err); }
self.emit('error ignored', err);
}
});
this._proxy.connect();
};
/**
* [close description]
* @return {[type]} [description]
*/
Socket.prototype.close = function(serverEnded){
var self = this;
self.connected = false;
self.closing = !serverEnded;
if (self.closing){
self.write(function(){
self._proxy.close();
self.emit('close');
});
return
}
var retry = ~~self.retry;
self.emit('end');
if(!retry) { return };
setTimeout(function(){
self.emit('reconnecting');
self.connect({reConnect:true});
}, retry);
};
Socket.prototype.write = function(data, fn) {
if ('function' == typeof data) {
fn = data;
data = null;
}
data = (data) ? ('' + data) : '';
var msg = Ti.createBuffer({value: data});
var callback = fn || function(){};
Ti.Stream.write(this._connection, msg, function(){
callback([].slice(arguments));
});
};
/**
* [setKeepAlive description]
* @param {[type]} enable [description]
* @param {[type]} initialDelay [description]
*/
Socket.prototype.setKeepAlive = function(enable, initialDelay) {
var self = this;
if (!enable) {
self._keepAlive && clearInterval(self._keepAlive);
self._keepAlive = null;
return;
}
self._keepAlive = setInterval(function(){
self.write('ping');
},initialDelay || 300000);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment