Module: GameServer::BaseListner

Includes:
DaemonLogger::Mixins
Defined in:
lib/base_listner.rb

Overview

Базовый модуль для прослушивания JSON запросов от клиента

Constant Summary collapse

MAX_INPUT_BUFFER_SIZE =
128 * 1024

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from DaemonLogger::Mixins

#log, #log_exception, #with_exception_logging

Instance Attribute Details

#input_bufferObject

В этом буфере хранится начало сообщения от клиента, если оно вдруг разбилось на несколько кусоков данных



71
72
73
# File 'lib/base_listner.rb', line 71

def input_buffer
  @input_buffer
end

#process_semaphoreObject

send_data_semaphore -семафор (mutex) для доступа к коннекшену. если не установлен - то не используется. может устанавливаться в приложении connection.send_data_semaphore = Mutex.new process_semaphore - семафор для обработки



9
10
11
# File 'lib/base_listner.rb', line 9

def process_semaphore
  @process_semaphore
end

#send_data_semaphoreObject

send_data_semaphore -семафор (mutex) для доступа к коннекшену. если не установлен - то не используется. может устанавливаться в приложении connection.send_data_semaphore = Mutex.new process_semaphore - семафор для обработки



9
10
11
# File 'lib/base_listner.rb', line 9

def send_data_semaphore
  @send_data_semaphore
end

Instance Method Details

#connection_infoObject



38
39
40
# File 'lib/base_listner.rb', line 38

def connection_info
  "CONNECTION"
end

#critical_error(e) ⇒ Object



63
64
65
66
67
# File 'lib/base_listner.rb', line 63

def critical_error(e)
  log_exception e
  send_error(e.class.to_s.underscore)
#    close_connection_after_writing
end

#find_controller(request) ⇒ Object



21
22
23
24
25
26
27
28
# File 'lib/base_listner.rb', line 21

def find_controller(request)
  return unless request.name =~ /^[A-Za-z_]+$/
  controller_name = (controllers_classes_root + "::" + request.name.camelize)
  log controller_name
  controller_name.constantize
rescue NameError
  return
end

#initialize(*args) ⇒ Object



15
16
17
18
19
# File 'lib/base_listner.rb', line 15

def initialize(*args)
  super(*args)
  self.input_buffer = ""
  self.process_semaphore = Mutex.new
end

#policy_file_request(data) ⇒ Object



121
122
123
124
125
126
127
128
# File 'lib/base_listner.rb', line 121

def policy_file_request(data)
  if data =~ /^<policy-file-request/
    send_data(File.open(Rails.root + 'config/crossdomain.xml' + "\000").read)
    #close_connection_after_writing
    return true
  end
  return false
end

#process_query(query_string) ⇒ Object

Обработать один запрос



105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/base_listner.rb', line 105

def process_query(query_string)
  request = GameServer::RequestParser.new(query_string).parse
  controller = find_controller(request)
  return send_error('unknown_request', request.name) unless controller
  controller.new(self, request, GameServer::ObjectSpace.instance).run
rescue GameServer::RequestParser::ParserError
  send_error('bad_syntax')
rescue GameServer::ServerError => e
  send_error("server_error", "#{e.name} #{!(e.comment.empty?) ? ':' + e.comment : ''}")
rescue GameError => e
  send_error(e.class.to_s.underscore, e.message)
rescue => e
  critical_error(e)
end

#process_whole_message(message) ⇒ Object



98
99
100
101
102
# File 'lib/base_listner.rb', line 98

def process_whole_message(message)
  message.split("\n").each do |query_string|
    process_semaphore.synchronize{ process_query(query_string) }
  end
end

#receive_data(data) ⇒ Object

Обработать входящие данные (может быть несклько строк запросов в одном пакете данных)



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/base_listner.rb', line 74

def receive_data(data)
  data.gsub!("\000", "")

  complete_message = input_buffer + data
  if complete_message[-1] != "\n"
    self.input_buffer = complete_message
    if input_buffer.size >= MAX_INPUT_BUFFER_SIZE
      self.input_buffer.clear
      raise "OVERFLOW OF INPUT BUFFER #{input_buffer.size}"
    end
    return
  else
    input_buffer.clear
  end

  log "Received from #{connection_info} (size #{complete_message.size}): " + complete_message.inspect
  return if policy_file_request(complete_message)
  operation = proc { process_whole_message(complete_message) }
  callback = proc { nil }
  EventMachine.defer(operation, callback)
rescue => e
  critical_error(e)
end

#send_data(data) ⇒ Object



52
53
54
55
56
57
58
59
60
# File 'lib/base_listner.rb', line 52

def send_data(data)
  log "Data sended to #{connection_info}: " + data#.inspect

  if send_data_semaphore
    send_data_semaphore.synchronize { super(data) }
  else
    super(data)
  end
end

#send_error(name, comment = "") ⇒ Object



30
31
32
# File 'lib/base_listner.rb', line 30

def send_error(name, comment = "")
  send_line(['error', name, comment].to_json )
end

#send_json(object) ⇒ Object



43
44
45
46
# File 'lib/base_listner.rb', line 43

def send_json(object)
  #send_line '<?xml version="1.0" encoding="UTF-8"?>' + "\n<message>\n" + object.to_json + "\n</message>\n\000"
  send_line object.to_json
end

#send_json_with_marker(marker, object) ⇒ Object



48
49
50
# File 'lib/base_listner.rb', line 48

def send_json_with_marker(marker, object)
  send_json [marker, object]
end

#send_line(string) ⇒ Object



34
35
36
# File 'lib/base_listner.rb', line 34

def send_line(string)
  send_data(string + "\000\n" )
end