export default class ClientDriver{ /* (0) Constants & Enums ---------------------------------------------------------*/ static get STATE(){ return Object.freeze({ CLOSED: 0, READY: 1, CONNECTING: 2, CONNECTED: 3, TRANFERING: 4 }); } /* (1) Creates a client driver * * @_resource Target resource (typically an URL) * @_auth Authentication data (depends on Driver implementation) * ---------------------------------------------------------*/ constructor(_resource, _auth={}){ /* (1) Initialize driver ---------------------------------------------------------*/ /* (1) Default attributes values */ this.force_close = false; this.state = ClientDriver.STATE.READY; this.stack = []; this.error = false; /* (2) Default User callbacks */ this.callback = { onconnected: function(){}, onclose: function(){}, onreceive: function(){} }; this.event = { /* (3) Manage connection opened */ onconnected: function(){ // update state this.state = ClientDriver.STATE.CONNECTED; // call callback this.callback.onconnected(); // if request(s) in stack -> pop & send them while( this.stack.length > 0 ) this.send(this.stack.shift()); }.bind(this), /* (4) Manage connection closed */ onclose: function(){ // if called close() -> CLOSED if( this.force_close ) this.state = ClientDriver.STATE.CLOSED; // else set state back to READY else this.state = ClientDriver.STATE.READY; // call callback this.callback.onclose(); }.bind(this), /* (5) Manage response received */ onreceive: function(_response){ // set state from TRANSFERING to CONNECTED this.state = ClientDriver.STATE.CONNECTED; // call callback this.callback.onreceive(_response); }.bind(this) }; /* (2) Manage errors ---------------------------------------------------------*/ /* (1) Fail: invalid _resource */ if( typeof _resource !== 'string' ) return ( this.error = true ); /* (2) Set explicit attributes */ this.resource = _resource; this.auth = _auth; return; } /* (2) Binds the client to the resource * * @return bound Whether the binding has been successful * ---------------------------------------------------------*/ bind(){ /* (1) force_close -> fail */ if( this.force_close ) return false; /* (2) Fail: not READY */ if( this.state !== ClientDriver.STATE.READY ) return false; /* (3) Update state */ this.state = ClientDriver.STATE.CONNECTING; /* (4) Child dispatch */ return true; } /* (3) Closes the connection * * @return closed Whether the connection has been closed * ---------------------------------------------------------*/ close(){ /* (1) set force_close */ this.force_close = true; /* (2) Update state */ this.state = ClientDriver.STATE.CLOSED; /* (4) Child dispatch */ return true; } /* (4) Send request * * @_request Request data * * @return sent Whether the request has been successful * ---------------------------------------------------------*/ send(_request){ /* (1) force_close -> fail */ if( this.force_close ) return false; /* (2) bufferise 'state' */ let state = this.state; /* (3) Fail: invalid _request */ if( !(_request instanceof Object) ) return false; /* (4) CLOSED -> abort */ if( state === ClientDriver.STATE.CLOSED ) return false; /* (5) READY -> stack message + bind() [in case connection failed)] */ if( state === ClientDriver.STATE.READY ) return ( this.stack.push(_request) > -1 ) && this.bind(); /* (6) CONNECTING -> stack message */ if( state === ClientDriver.STATE.CONNECTING ) return ( this.stack.push(_request) > -1 ); /* (7) update state */ this.state = ClientDriver.STATE.TRANFERING; /* (8) Child dispatch */ return true; } /* (5) Bind event to connection successfully opened * * @_callback Callback launched when connection is opened * * @return bound Whether the callback has successfully been bound * ---------------------------------------------------------*/ set onconnected(_callback){ /* (1) Fail: invalid _callback */ if( !(_callback instanceof Function) ) return false; /* (2) Register _callback */ this.callback.onconnected = _callback; /* (3) By default return success */ return true; } /* (6) Bind event to connection closed * * @_callback Callback launched when connection is closed * * @return bound Whether the callback has successfully been bound * ---------------------------------------------------------*/ set onclose(_callback){ /* (1) Fail: invalid _callback */ if( !(_callback instanceof Function) ) return false; /* (2) Register _callback */ this.callback.onclose = _callback; /* (3) By default return success */ return true; } /* (7) Bind event to message reception * * @_callback Callback launched when a message is received * * @return bound Whether the callback has successfully been bound * ---------------------------------------------------------*/ set onreceive(_callback){ /* (1) Fail: invalid _callback */ if( !(_callback instanceof Function) ) return false; /* (2) Register _callback */ this.callback.onreceive = _callback; /* (3) By default return success */ return true; } }