long_polling_controller.rb 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. # Copyright (C) 2012-2013 Zammad Foundation, http://zammad-foundation.org/
  2. class LongPollingController < ApplicationController
  3. skip_filter :session_update
  4. # GET /api/v1/message_send
  5. def message_send
  6. new_connection = false
  7. # check client id
  8. client_id = client_id_verify
  9. if !client_id
  10. new_connection = true
  11. client_id = client_id_gen
  12. log 'notice', "new client connection", client_id
  13. end
  14. if !params['data']
  15. params['data'] = {}
  16. end
  17. # spool messages for new connects
  18. if params['data']['spool']
  19. msg = JSON.generate( params['data'] )
  20. Sessions.spool_create(msg)
  21. end
  22. # get spool messages and send them to new client connection
  23. if params['data']['action'] == 'spool'
  24. # error handling
  25. if params['data']['timestamp']
  26. log 'notice', "request spool data > '#{Time.at( params['data']['timestamp'] ).to_s}'", client_id
  27. else
  28. log 'notice', "request spool init data", client_id
  29. end
  30. if current_user
  31. spool = Sessions.spool_list( params['data']['timestamp'], current_user.id )
  32. spool.each { |item|
  33. if item[:type] == 'direct'
  34. log 'notice', "send spool to (user_id=#{ current_user.id })", client_id
  35. Sessions.send( client_id, item[:message] )
  36. else
  37. log 'notice', "send spool", client_id
  38. Sessions.send( client_id, item[:message] )
  39. end
  40. }
  41. end
  42. # send spool:sent event to client
  43. sleep 0.2
  44. log 'notice', "send spool:sent event", client_id
  45. Sessions.send( client_id, { :event => 'spool:sent', :data => { :timestamp => Time.now.utc.to_i } } )
  46. end
  47. # receive message
  48. if params['data']['action'] == 'login'
  49. user_id = session[:user_id]
  50. user = {}
  51. if user_id
  52. user = User.user_data_full( user_id )
  53. end
  54. log 'notice', "send auth login (user_id #{user_id})", client_id
  55. Sessions.create( client_id, user, { :type => 'ajax' } )
  56. # broadcast
  57. elsif params['data']['action'] == 'broadcast'
  58. # list all current clients
  59. client_list = Sessions.list
  60. client_list.each {|local_client_id, local_client|
  61. if local_client_id != client_id
  62. # broadcast to recipient list
  63. if params['data']['recipient'] && params['data']['recipient']['user_id']
  64. params['data']['recipient']['user_id'].each { |user_id|
  65. if local_client[:user][:id] == user_id
  66. log 'notice', "send broadcast from (#{client_id.to_s}) to (user_id #{user_id})", local_client_id
  67. Sessions.send( local_client_id, params['data'] )
  68. end
  69. }
  70. # broadcast every client
  71. else
  72. log 'notice', "send broadcast from (#{client_id.to_s})", local_client_id
  73. Sessions.send( local_client_id, params['data'] )
  74. end
  75. else
  76. log 'notice', "do not send broadcast to it self", client_id
  77. end
  78. }
  79. end
  80. if new_connection
  81. result = { :client_id => client_id }
  82. render :json => result
  83. else
  84. render :json => {}
  85. end
  86. end
  87. # GET /api/v1/message_receive
  88. def message_receive
  89. # check client id
  90. client_id = client_id_verify
  91. if !client_id
  92. render :json => { :error => 'Invalid client_id receive!' }, :status => :unprocessable_entity
  93. return
  94. end
  95. # check queue to send
  96. begin
  97. # update last ping
  98. 4.times {|loop|
  99. sleep 0.25
  100. }
  101. #sleep 1
  102. Sessions.touch( client_id )
  103. # set max loop time to 24 sec. because of 30 sec. timeout of mod_proxy
  104. count = 12
  105. while true
  106. count = count - 1
  107. queue = Sessions.queue( client_id )
  108. if queue && queue[0]
  109. # puts "send " + queue.inspect + client_id.to_s
  110. render :json => queue
  111. return
  112. end
  113. 8.times {|loop|
  114. sleep 0.25
  115. }
  116. #sleep 2
  117. if count == 0
  118. render :json => { :action => 'pong' }
  119. return
  120. end
  121. end
  122. rescue Exception => e
  123. puts e.inspect
  124. puts e.backtrace
  125. render :json => { :error => 'Invalid client_id in receive loop!' }, :status => :unprocessable_entity
  126. return
  127. end
  128. end
  129. private
  130. def client_id_gen
  131. rand(9999999999).to_s
  132. end
  133. def client_id_verify
  134. return if !params[:client_id]
  135. sessions = Sessions.sessions
  136. return if !sessions.include?( params[:client_id].to_s )
  137. return params[:client_id].to_s
  138. end
  139. def log( level, data, client_id = '-' )
  140. if false
  141. return if level == 'debug'
  142. end
  143. puts "#{Time.now}:client(#{ client_id }) #{ data }"
  144. # puts "#{Time.now}:#{ level }:client(#{ client_id }) #{ data }"
  145. end
  146. end