long_polling_controller.rb 4.8 KB

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