|
@@ -9,7 +9,7 @@ class App.WebSocket
|
|
|
|
|
|
@close: (args) -> # Must be a static method
|
|
|
if _instance isnt undefined
|
|
|
- _instance.close()
|
|
|
+ _instance.close(args)
|
|
|
|
|
|
@send: (args) -> # Must be a static method
|
|
|
@connect()
|
|
@@ -20,6 +20,7 @@ class App.WebSocket
|
|
|
_instance.auth(args)
|
|
|
|
|
|
@_spool: ->
|
|
|
+ @connect()
|
|
|
_instance.spool()
|
|
|
|
|
|
# The actual Singleton class
|
|
@@ -27,9 +28,12 @@ class _Singleton extends App.Controller
|
|
|
@include App.Log
|
|
|
|
|
|
queue: []
|
|
|
- supported: true
|
|
|
- lastSpoolMessage: undefined
|
|
|
- connectionEstablished: false
|
|
|
+ supported: true
|
|
|
+ lastSpoolMessage: undefined
|
|
|
+ connectionEstablished: false
|
|
|
+ connectionWasEstablished: false
|
|
|
+ backend: 'websocket'
|
|
|
+ client_id: undefined
|
|
|
|
|
|
constructor: (@args) ->
|
|
|
|
|
@@ -46,19 +50,22 @@ class _Singleton extends App.Controller
|
|
|
@connect()
|
|
|
|
|
|
send: (data) =>
|
|
|
- return if !@supported
|
|
|
-# console.log 'ws:send trying', data, @ws, @ws.readyState
|
|
|
-
|
|
|
- # A value of 0 indicates that the connection has not yet been established.
|
|
|
- # A value of 1 indicates that the connection is established and communication is possible.
|
|
|
- # A value of 2 indicates that the connection is going through the closing handshake.
|
|
|
- # A value of 3 indicates that the connection has been closed or could not be opened.
|
|
|
- if @ws.readyState is 0
|
|
|
- @queue.push data
|
|
|
+ if @backend is 'ajax'
|
|
|
+ @_ajaxSend(data)
|
|
|
else
|
|
|
-# console.log( 'ws:send', data )
|
|
|
- string = JSON.stringify( data )
|
|
|
- @ws.send(string)
|
|
|
+
|
|
|
+# console.log 'ws:send trying', data, @ws, @ws.readyState
|
|
|
+
|
|
|
+ # A value of 0 indicates that the connection has not yet been established.
|
|
|
+ # A value of 1 indicates that the connection is established and communication is possible.
|
|
|
+ # A value of 2 indicates that the connection is going through the closing handshake.
|
|
|
+ # A value of 3 indicates that the connection has been closed or could not be opened.
|
|
|
+ if @ws.readyState is 0
|
|
|
+ @queue.push data
|
|
|
+ else
|
|
|
+# console.log( 'ws:send', data )
|
|
|
+ string = JSON.stringify( data )
|
|
|
+ @ws.send(string)
|
|
|
|
|
|
auth: (data) =>
|
|
|
return if !@supported
|
|
@@ -77,7 +84,7 @@ class _Singleton extends App.Controller
|
|
|
if @lastSpoolMessage
|
|
|
data['timestamp'] = @lastSpoolMessage
|
|
|
|
|
|
- @log 'Event', 'debug', 'spool', data
|
|
|
+ @log 'Websocket', 'debug', 'spool', data
|
|
|
|
|
|
# ask for spool messages
|
|
|
App.Event.trigger(
|
|
@@ -89,37 +96,38 @@ class _Singleton extends App.Controller
|
|
|
@lastSpoolMessage = Math.round( +new Date()/1000 )
|
|
|
|
|
|
close: =>
|
|
|
- return if !@supported
|
|
|
+ return if @backend is 'ajax'
|
|
|
|
|
|
@ws.close()
|
|
|
|
|
|
ping: =>
|
|
|
- return if !@supported
|
|
|
+ return if @backend is 'ajax'
|
|
|
|
|
|
- @log 'Event', 'debug', 'send websockend ping'
|
|
|
+ @log 'Websocket', 'debug', 'send websockend ping'
|
|
|
@send( { action: 'ping' } )
|
|
|
|
|
|
# check if ping is back within 2 min
|
|
|
@clearDelay('websocket-ping-check')
|
|
|
check = =>
|
|
|
- @log 'Event', 'notice', 'no websockend ping response, reconnect...'
|
|
|
+ @log 'Websocket', 'notice', 'no websockend ping response, reconnect...'
|
|
|
@close()
|
|
|
@delay check, 120000, 'websocket-ping-check'
|
|
|
|
|
|
pong: ->
|
|
|
- return if !@supported
|
|
|
- @log 'Event', 'debug', 'received websockend ping'
|
|
|
+ return if @backend is 'ajax'
|
|
|
+
|
|
|
+ @log 'Websocket', 'debug', 'received websockend ping'
|
|
|
|
|
|
# test again after 1 min
|
|
|
@delay @ping, 60000
|
|
|
|
|
|
connect: =>
|
|
|
+ return if @backend is 'ajax'
|
|
|
|
|
|
if !window.WebSocket
|
|
|
- @error = new App.ErrorModal(
|
|
|
- message: 'Sorry, no websocket support!'
|
|
|
- )
|
|
|
- @supported = false
|
|
|
+ @backend = 'ajax'
|
|
|
+ @log 'WebSocket', 'notice', 'no support of websocket, use ajax long polling'
|
|
|
+ @_ajaxInit()
|
|
|
return
|
|
|
|
|
|
protocol = 'ws://'
|
|
@@ -130,9 +138,10 @@ class _Singleton extends App.Controller
|
|
|
|
|
|
# Set event handlers.
|
|
|
@ws.onopen = =>
|
|
|
- @log 'Event', 'notice', 'new websocked connection open'
|
|
|
+ @log 'Websocket', 'notice', 'new websocket connection open'
|
|
|
|
|
|
@connectionEstablished = true
|
|
|
+ @connectionWasEstablished = true
|
|
|
|
|
|
# close error message show up (because try so connect again) if exists
|
|
|
@clearDelay('websocket-no-connection-try-reconnect')
|
|
@@ -144,7 +153,7 @@ class _Singleton extends App.Controller
|
|
|
|
|
|
# empty queue
|
|
|
for item in @queue
|
|
|
- @log 'Event', 'debug', 'empty ws queue', item
|
|
|
+ @log 'Websocket', 'debug', 'empty ws queue', item
|
|
|
@send(item)
|
|
|
@queue = []
|
|
|
|
|
@@ -153,41 +162,31 @@ class _Singleton extends App.Controller
|
|
|
|
|
|
@ws.onmessage = (e) =>
|
|
|
pipe = JSON.parse( e.data )
|
|
|
- @log 'Event', 'debug', 'ws:onmessage', pipe
|
|
|
-
|
|
|
- # go through all blocks
|
|
|
- for item in pipe
|
|
|
-
|
|
|
- # reset reconnect loop
|
|
|
- if item['action'] is 'pong'
|
|
|
- @pong()
|
|
|
-
|
|
|
- # fill collection
|
|
|
- if item['collection']
|
|
|
- @log 'Event', 'debug', "ws:onmessage collection:" + item['collection']
|
|
|
- App.Store.write( item['collection'], item['data'] )
|
|
|
-
|
|
|
- # fire event
|
|
|
- if item['event']
|
|
|
- if typeof item['event'] is 'object'
|
|
|
- for event in item['event']
|
|
|
- @log 'Event', 'debug', "ws:onmessage event:" + event
|
|
|
- App.Event.trigger( event, item['data'] )
|
|
|
- else
|
|
|
- @log 'Event', 'debug', "ws:onmessage event:" + item['event']
|
|
|
- App.Event.trigger( item['event'], item['data'] )
|
|
|
+ @log 'Websocket', 'debug', 'ws:onmessage', pipe
|
|
|
+ @_receiveMessage(pipe)
|
|
|
|
|
|
@ws.onclose = (e) =>
|
|
|
- @log 'Event', 'debug', "ws:onclose", e
|
|
|
+ @log 'Websocket', 'debug', "ws:onclose", e
|
|
|
|
|
|
# set timestamp to get spool messages later
|
|
|
if @connectionEstablished
|
|
|
@lastSpoolMessage = Math.round( +new Date()/1000 )
|
|
|
@connectionEstablished = false
|
|
|
|
|
|
+ return if @backend is 'ajax'
|
|
|
+
|
|
|
# show error message, first try to reconnect
|
|
|
if !@error
|
|
|
message = =>
|
|
|
+
|
|
|
+ # use fallback if no connection was possible
|
|
|
+ if !@connectionWasEstablished
|
|
|
+ @backend = 'ajax'
|
|
|
+ @log 'WebSocket', 'notice', 'No connection to websocket, use use ajax long polling as fallback'
|
|
|
+ @_ajaxInit()
|
|
|
+ return
|
|
|
+
|
|
|
+ # show reconnect message
|
|
|
@error = new App.ErrorModal(
|
|
|
message: 'No connection to websocket, trying to reconnect...'
|
|
|
)
|
|
@@ -197,5 +196,110 @@ class _Singleton extends App.Controller
|
|
|
@delay @connect, 4500
|
|
|
|
|
|
@ws.onerror = (e) =>
|
|
|
- @log 'Event', 'debug', "ws:onerror", e
|
|
|
+ @log 'Websocket', 'debug', "ws:onerror", e
|
|
|
+
|
|
|
+ _receiveMessage: (data = []) =>
|
|
|
+
|
|
|
+ # go through all blocks
|
|
|
+ for item in data
|
|
|
|
|
|
+ # reset reconnect loop
|
|
|
+ if item['action'] is 'pong'
|
|
|
+ @pong()
|
|
|
+
|
|
|
+ # fill collection
|
|
|
+ if item['collection']
|
|
|
+ @log 'Websocket', 'debug', "onmessage collection:" + item['collection']
|
|
|
+ App.Store.write( item['collection'], item['data'] )
|
|
|
+
|
|
|
+ # fire event
|
|
|
+ if item['event']
|
|
|
+ if typeof item['event'] is 'object'
|
|
|
+ for event in item['event']
|
|
|
+ @log 'Websocket', 'debug', "onmessage event:" + event
|
|
|
+ App.Event.trigger( event, item['data'] )
|
|
|
+ else
|
|
|
+ @log 'Websocket', 'debug', "onmessage event:" + item['event']
|
|
|
+ App.Event.trigger( item['event'], item['data'] )
|
|
|
+
|
|
|
+ _ajaxInit: (data = {}) =>
|
|
|
+
|
|
|
+ # return if init is already done and not forced
|
|
|
+ return if @_ajaxInitDone && !data.force
|
|
|
+
|
|
|
+ # stop init request if new one is started
|
|
|
+ if @_ajaxInitWorking
|
|
|
+ console.log '@_ajaxInitWorking', @_ajaxInitWorking
|
|
|
+ @_ajaxInitWorking.abort()
|
|
|
+
|
|
|
+ # call init request
|
|
|
+ @_ajaxInitWorking = App.Com.ajax(
|
|
|
+ type: 'POST'
|
|
|
+ url: '/api/message_send'
|
|
|
+ data: JSON.stringify({ data: { action: 'login' } })
|
|
|
+ processData: false
|
|
|
+ queue: false
|
|
|
+ success: (data) =>
|
|
|
+ if data.client_id
|
|
|
+ @log 'Websocket', 'notice', 'ajax:new client_id', data.client_id
|
|
|
+ @client_id = data.client_id
|
|
|
+ @_ajaxReceive()
|
|
|
+ @_ajaxSendQueue()
|
|
|
+ @_ajaxInitDone = true
|
|
|
+ @_ajaxInitWorking = false
|
|
|
+ error: =>
|
|
|
+ @_ajaxInitDone = true
|
|
|
+ @_ajaxInitWorking = false
|
|
|
+ )
|
|
|
+
|
|
|
+ _ajaxSend: (data) =>
|
|
|
+ @log 'Websocket', 'debug', 'ajax:sendmessage', data
|
|
|
+ if !@client_id || @client_id is undefined || !@_ajaxInitDone
|
|
|
+ @_ajaxInit()
|
|
|
+ @queue.push data
|
|
|
+ else
|
|
|
+ @queue.push data
|
|
|
+ @_ajaxSendQueue()
|
|
|
+
|
|
|
+ _ajaxSendQueue: =>
|
|
|
+ while !_.isEmpty(@queue)
|
|
|
+ data = @queue.shift()
|
|
|
+ App.Com.ajax(
|
|
|
+ type: 'POST'
|
|
|
+ url: '/api/message_send'
|
|
|
+ data: JSON.stringify({ client_id: @client_id, data: data })
|
|
|
+ processData: false
|
|
|
+ queue: true
|
|
|
+ success: (data) =>
|
|
|
+ if data && data.error
|
|
|
+ @client_id = undefined
|
|
|
+ @_ajaxInit( force: true )
|
|
|
+ error: =>
|
|
|
+ @client_id = undefined
|
|
|
+ @_ajaxInit( force: true )
|
|
|
+ )
|
|
|
+
|
|
|
+ _ajaxReceive: =>
|
|
|
+ return if !@client_id
|
|
|
+ return if @_ajaxReceiveWorking is true
|
|
|
+ @_ajaxReceiveWorking = true
|
|
|
+ App.Com.ajax(
|
|
|
+ id: 'message_receive',
|
|
|
+ type: 'POST'
|
|
|
+ url: '/api/message_receive'
|
|
|
+ data: JSON.stringify({ client_id: @client_id })
|
|
|
+ processData: false
|
|
|
+ success: (data) =>
|
|
|
+ @log 'Websocket', 'notice', 'ajax:onmessage', data
|
|
|
+ @_receiveMessage(data)
|
|
|
+ if data && data.error
|
|
|
+ @client_id = undefined
|
|
|
+ @_ajaxInit( force: true )
|
|
|
+ @_ajaxReceiveWorking = false
|
|
|
+ @_ajaxReceive()
|
|
|
+ error: (data) =>
|
|
|
+ @client_id = undefined
|
|
|
+ @_ajaxInit( force: true )
|
|
|
+ @_ajaxReceiveWorking = false
|
|
|
+ @delay @_ajaxReceive, 5000
|
|
|
+ )
|