From d077cdc9092b600b947f55a761981cfe5284c04d Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Wed, 4 Apr 2018 11:19:31 +0200 Subject: [PATCH] [lib.client.ws] internal token management (stack kept while token does not match + pop stack only when valid token, else call onclose()) [lib.content-controller] added ws_connect() + ws_handler() [lib.channel-controller] now use ws_connect() --- webpack/lib/channel-controller.js | 12 +---- webpack/lib/client/ws.js | 59 +++++++++++++++++++----- webpack/lib/content-controller.js | 75 ++++++++++++++++++++++++++++--- 3 files changed, 118 insertions(+), 28 deletions(-) diff --git a/webpack/lib/channel-controller.js b/webpack/lib/channel-controller.js index 6a676b2..7fc7bf0 100644 --- a/webpack/lib/channel-controller.js +++ b/webpack/lib/channel-controller.js @@ -48,18 +48,8 @@ export default class ChannelController{ gs.get.room.fetch(); /* (6) Open channel websocket */ - ( window.csock != null ) && csock.close(); - window.csock = new wscd(`wss://ws.douscord.xdrm.io/channel/${channel.id}`, { token: auth.token }); - csock.onreceive = (_dat) => { + gs.get.content.ws_connect(); - if( _dat.error !== 0 ) - return console.log('[WS] auth failed'); - - csock.send({ buffer: { rid: gs.get.content.rid } }); - - csock.onreceive = gs.get.content.manage_update; - }; - csock.bind(); /* (6) Log channel */ // console.log(`[channel.current] ${channel.link} (${channel.label})`); diff --git a/webpack/lib/client/ws.js b/webpack/lib/client/ws.js index 5e0efa8..cc4e504 100644 --- a/webpack/lib/client/ws.js +++ b/webpack/lib/client/ws.js @@ -25,19 +25,59 @@ export default class WebSocketClientDriver extends ClientDriver{ let tmp = typeof _auth !== 'object' || _auth['token'] == null || typeof _auth.token !== 'string'; this.auth = (tmp) ? { token: null } : { token: _auth.token }; - /* (2) Create useful attributes */ + /* (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(){ - /* (3) Manage response received */ - this.event.onreceive = function(_response){ - - // set state from TRANSFERING to CONNECTED + // update state this.state = ClientDriver.STATE.CONNECTED; - // call callback - this.callback.onreceive( JSON.parse(_response) ); + // 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) @@ -70,9 +110,6 @@ export default class WebSocketClientDriver extends ClientDriver{ /* (5) Bind callback.onreceive */ this.ws.onmessage = (_message_event) => this.event.onreceive(_message_event.data); - /* (6) Send authentication token */ - this.send({ buffer: { token: this.auth.token } }); - /* (6) Return success */ return true; @@ -89,7 +126,7 @@ export default class WebSocketClientDriver extends ClientDriver{ ---------------------------------------------------------*/ send(_request){ - var buffer = '{ "token": null }'; + var buffer = null; /* (0) Parent check */ if( !super.send(_request) ) diff --git a/webpack/lib/content-controller.js b/webpack/lib/content-controller.js index 83bd3f1..9acca39 100644 --- a/webpack/lib/content-controller.js +++ b/webpack/lib/content-controller.js @@ -142,10 +142,72 @@ export default class ContentController{ } - /* (9) MAIN UPDATER + /* (9) Websocket connection / reconnection * ---------------------------------------------------------*/ - manage_update(_dat){ + ws_connect(){ + + console.warn(`new ws(/channel/${this.cid})`); + + // 1. Close websocket if exists + if ( window.csock instanceof wscd ) + csock.close(); + + // 2. Create new connection + window.csock = new wscd(`wss://ws.douscord.xdrm.io/channel/${this.cid}`, { token: auth.token }); + + // 3. Bind events + csock.onreceive = gs.get.content.ws_handler.bind({ event: 'receive' }); + csock.onclose = gs.get.content.ws_handler.bind({ event: 'close' }); + + // 4. Start communication + csock.bind(); + + } + + + /* (10) Websocket connection manager + * + * @this.event Event type : + * 'close' -> socket closed + * 'receive' -> received message + * + ---------------------------------------------------------*/ + ws_handler(_response){ + + console.warn('ws(', this.event, _response || '', ')'); + + if( this.event === null ) + return; + + /* (2) CLOSE event -> reconnect in 500ms + ---------------------------------------------------------*/ + if( this.event === 'close' ) + return setTimeout(gs.get.content.ws_connect.bind(gs.get.content), 500); + + + /* (3) RECEIVE event + ---------------------------------------------------------*/ + if( this.event === 'receive' ){ + + /* (1) Communication error -> reconnect in 500ms */ + if( typeof _response !== 'object' ) + return setTimeout(gs.get.content.ws_connect.bind(gs.get.content), 500); + + /* (2) If message update -> update interface model */ + gs.get.content.ws_to_model(_response); + + } + + } + + + + /* (11) MAIN UPDATER + * + ---------------------------------------------------------*/ + ws_to_model(_dat){ + /* (1) Manage rooms DELETE ---------------------------------------------------------*/ @@ -187,13 +249,13 @@ export default class ContentController{ let existing_index = -1; - for( let t in current_list ){ + main_loop: for( let t in current_list ){ for( let r in current_list[t].list ){ if( current_list[t].list[r].id === ri ){ existing_index = r; - break; + break main_loop; } } @@ -272,12 +334,13 @@ export default class ContentController{ /* (4) Manage channels CREATE ---------------------------------------------------------*/ for( let c of _dat.channels.add ){ + console.log(c); - gs.get.channel.dump({ + gs.get.channel.dump([{ id: parseInt(c.id), label: c.name, link: c.link - }, true); + }], true); }