Advertisement
Guest User

Empyreal Client in javascript.

a guest
Feb 8th, 2013
203
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /**
  2.  * @author Marten Koedam
  3.  * @copyright 2013, Dalines Software Library
  4.  *
  5.  * For more information see http://sanctorium.org
  6.  */
  7. var createModel = require('./models.js');
  8. var settings = require('./settings.js');
  9.  
  10. var EMPYREAL_SERVER = {
  11.     host: settings.EMPYREAL_SERVER_HOST,
  12.     port: settings.EMPYREAL_SERVER_PORT
  13. };
  14. /**
  15.  * Client object to connect to the Empyreal Server with the correct protocol.
  16.  *
  17.  * Use the send method to trigger actions on the server and add callbacks to be executed with the return value.
  18.  * This is asynchronous so the callbacks are stored per UID which is send back and forth with the server.
  19.  *
  20.  * For more information see the Empyreal documentation at http://empyreal.sanctorium.org
  21.  */
  22. var EmpyrealClient = function (listener) {
  23.  
  24.     this._broadcastListener = listener;
  25.     this._callbacks = {};
  26.     this._errbacks = {}
  27.  
  28.     this._broadcasted = {}; // List with UIDs to not fire the same broadcast message twice... eep?
  29.  
  30.     this.id = this._generateUniqueID();
  31.  
  32. };
  33.  
  34. EmpyrealClient.prototype = {
  35.     /**
  36.      * Connects to the Empyreal server and adds a listener.
  37.      */
  38.     connect : function (cb) {
  39.    
  40.         cb = cb ? cb : function () {};
  41.    
  42.         var net = require('net');
  43.         this.client = net.createConnection(EMPYREAL_SERVER, function () {});
  44.         this.client.on('data', this.processResponse.bind(this), cb);
  45.  
  46.     },
  47.     /**
  48.      * An object which can handle the Broadcast calls.
  49.      */
  50.     setBroadcastListener : function ( listener ) {
  51.         this._broadcastListener = listener;
  52.     },
  53.     /**
  54.      * Generate a unique ID so we can add the callbacks for it.
  55.      */
  56.     _generateUniqueID : function () {
  57.         return 'yxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
  58.             var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
  59.             return v.toString(16);
  60.         });
  61.     },
  62.     /**
  63.      * Default success callback, just log.
  64.      */
  65.     cbSuccess : function ( answer ) {
  66.         console.log('Default cbSuccess: ', answer);
  67.     },
  68.     /**
  69.      * Default error callback, just log.
  70.      */
  71.     cbError : function ( answer ) {
  72.         console.error('Default cbError: ', answer);
  73.     },
  74.    
  75.     /**
  76.      * Send a command to the Empyreal server.
  77.      */
  78.     send : function ( cmd, args, callback, errback, scope ) {
  79.        
  80.         var uid = this._generateUniqueID();
  81.         var line = this.writeLine( cmd, args, uid);
  82.        
  83.         callback = callback ? callback : this.cbSuccess;
  84.         errback = errback ? errback : this.cbError;
  85.         scope = scope ? scope : this;
  86.  
  87.         this._callbacks[uid] = {
  88.             method: callback,
  89.             scope: scope
  90.         };
  91.  
  92.         this._errbacks[uid] = {
  93.             method: errback,
  94.             scope: scope
  95.         };
  96.        
  97.         this.client.write(line);
  98.  
  99.     },
  100.     /**
  101.      * JSON Serialize the command to send.
  102.      */
  103.     writeLine : function ( cmd, args, uid ) {
  104.  
  105.         args = args ? args : [];
  106.         uid = uid ? uid : null;
  107.         return JSON.stringify({command: cmd, args: args, uid: uid})+"\r\n"; // TODO: models?
  108.  
  109.     },
  110.     /**
  111.      * This is the hook we added on the client for the onData callback.
  112.      */
  113.     processResponse : function ( data ) {
  114.        
  115.         this._receive( data );
  116.    
  117.     },
  118.     /**
  119.      * Per received line we process the response.
  120.      */
  121.     _process : function ( response ) {
  122.         var status, answer, uid;
  123.         try {
  124.             var parsed = this.decodeJSON( response );
  125.         } catch ( e ) {
  126.             console.error(e);
  127.             throw e;
  128.         }
  129.  
  130.         var status = parsed.status;
  131.         var answer = parsed.answer;
  132.         var uid = parsed.uid;
  133.  
  134.         // We usually expect a status OK.
  135.         if( status == 'OK' ) {
  136.             if( uid ) {
  137.                 if( typeof this._callbacks[uid] == 'undefined' ) {
  138.                     // The callback must have been removed.
  139.                     return;
  140.                 }
  141.                 var cb = this._callbacks[uid];
  142.                 cb.method.call(cb.scope, answer);
  143.                 delete this._callbacks[uid];
  144.                 delete this._errbacks[uid];
  145.                 return;
  146.             }
  147.             this.cbSuccess(answer);
  148.             return
  149.         }
  150.         // BROADCAST Received.
  151.         if ( status == 'BROADCAST' ) {
  152.        
  153.             if(this._broadcastListener && (typeof this._broadcasted[uid] == 'undefined')) {
  154.                 this._broadcasted[uid] = true;
  155.                 this._broadcastListener.received( answer );
  156.                 return;
  157.             }
  158.             return;
  159.         }
  160.         // Not a status we wanted.
  161.         if( uid ) {
  162.             if( typeof this._errbacks[uid] == 'undefined' ) {
  163.                 // The callback must have been removed.
  164.                 return;
  165.             }
  166.             var cb = this._errbacks[uid];
  167.             cb.method.call(cb.scope, answer);
  168.             delete this._callbacks[uid];
  169.             delete this._errbacks[uid];
  170.             return;
  171.         }
  172.         throw Error(this+': RECEIVED status: '+status+'; args: '+answer+';');
  173.  
  174.     },
  175.     /**
  176.      * Receive a line from the server, delimiter is a new line.
  177.      */
  178.     _receive : function ( data ) {
  179.        
  180.         var response = /^(.*?)$/mg.exec(data.toString());
  181.         for(var i = 0; i < response.length; i++) {
  182.             this._process(response[i]);
  183.         }
  184.         // Test to see if this prevents us from receiving things twice.
  185.         delete data;
  186.  
  187.     },
  188.     /**
  189.      * Decode the JSON string with the Empyreal model wrapper.
  190.      */
  191.     decodeJSON : function ( response ) {
  192.        
  193.         return JSON.parse(response, function (k, v) {
  194.             return createModel(v);
  195.         });
  196.  
  197.     },
  198.     /**
  199.      * Close the connection
  200.      */
  201.     close : function () {
  202.        
  203.         this.client.end();
  204.        
  205.     },
  206.    
  207.     toString : function () {
  208.         return 'EmpyrealClient::'+this.id;
  209.     }
  210. };
  211.  
  212. var createClient = function () {
  213.     return new EmpyrealClient();
  214. };
  215.  
  216. module.exports.client = createClient;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement