import ClientDriver from './client-driver.js' export default class WebSocketClientDriver extends ClientDriver{ /* (1) Creates a client driver * * @_resource Target resource (typically an URL) * @_auth Authentication object * * [fornat::AuthObject] * { * token: string * } * ---------------------------------------------------------*/ constructor(_resource, _auth={token:null}){ /* (0) Parent check */ if( !super().error ) return; /* (1) Set inherited attributes */ this.resource = _resource; let tmp = typeof _auth !== 'object' || _auth['token'] == null || typeof _auth.token !== 'string'; this.auth = (tmp) ? { token: null } : { token: _auth.token }; /* (2) When token response is OK */ this.valid_token = false; /* (3) Create useful attributes */ this.ws = null; this.buffer = null; // useful when waiting for WebSocket to open /* (4) Manage connection opened */ this.event.onconnected = function(){ // update state this.state = ClientDriver.STATE.CONNECTED; // send token this.ws.send(JSON.stringify({ token: this.auth.token })); }.bind(this); /* (5) Manage response received */ this.event.onreceive = function(_response){ /* (1) set state from TRANSFERING to CONNECTED */ this.state = ClientDriver.STATE.CONNECTED; /* (2) Try to parse JSON */ var obj_resp = null; try{ obj_resp = JSON.parse(_response); }catch(e){} /* (3) JSON error -> send null */ if( obj_resp === null ) this.callback.onreceive( null ); /* (4) if TOKEN VALIDATION */ if( typeof obj_resp.error === 'number' ){ // invalid token -> tell connection closed if( obj_resp.error !== 0 ) return this.event.onclose(); // valid token -> connected this.callback.onconnected(); // if request(s) in stack -> pop & send them while( this.stack.length > 0 ) this.send(this.stack.shift()); return; } /* (5) Else -> pass message to callback */ this.callback.onreceive(obj_resp); }.bind(this) } /* (2) Binds the client to the resource * * @return bound Whether the binding has been successful * ---------------------------------------------------------*/ bind(){ /* (0) Parent check */ if( !super.bind() ) return false; /* (1) Create WebSocket client instance */ this.ws = new WebSocket(this.resource); /* (2) Bind callback.onready */ this.ws.onopen = this.event.onconnected; /* (3) Bind callback.onclose */ this.ws.onclose = this.event.onclose; /* (4) Bind callback.onerror */ this.ws.onerror = this.event.onclose; /* (5) Bind callback.onreceive */ this.ws.onmessage = (_message_event) => this.event.onreceive(_message_event.data); /* (6) Return success */ return true; } /* (3) Send request * * @_request Request data * * @return sent Whether the request has been successful * ---------------------------------------------------------*/ send(_request){ var buffer = null; /* (0) Parent check */ if( !super.send(_request) ) return false; this.state = ClientDriver.STATE.CONNECTED; /* (1) Error: invalid _request.buffer */ if( typeof _request.buffer === 'object' ) buffer = JSON.stringify(_request.buffer); else if( typeof _request.buffer === 'string' ) buffer = _request.buffer; else return false; /* (2) Send message */ this.ws.send(buffer); /* (3) Return success */ return true; } /* (3) Closes the connection * * @return closed Whether the connection has been closed * ---------------------------------------------------------*/ close(){ /* (0) Parent check */ if( !super.close() ) return false; /* (1) Close websocket */ this.ws.close(); /* (2) Return success */ return true; } }